// Resource.java
// $Id: Resource.java,v 1.5 1997/07/30 14:03:13 ylafon Exp $  
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.tools.resources;

import java.beans.*;

import w3c.tools.resources.event.*;

/**
 * A Resource provides two distinct functionalities:
 * <dl>
 * <dt>It acts as an accessor for attribute values:
 * <dd>A resource will generally be used as an access point for a number
 *     of attributes. The attribute values are not necessarily stored in
 *     the resource itself (ie that responsibility may be delegated to 
 *     a database, a spreadsheet, or some other form of toaster).<br>
 *     <code>getAttributeDescriptor</code>,
 *     <code>getValue</code>,
 *     <code>getValues</code>,
 *     <code>setValue</code>,
 *     <code>setValues</code>.
 * <dt>It (might) provides support for serializing itself:
 * <dd>This interface suggest that you use the Java serialization
 *     mechanism, which is itself highly customizable.<br>
 * <code>unload</code>
 * <dt>It can be plugged into a <em>resource space</em>
 * <dd>Resources are stored under a hierarchical resource space, as
 * such they <strong>must</strong> have at least a <em>name</em> to be
 * used to lookup it up.<br>
 * <code>getName</code>
 * <code>setName</code>
 * <code>resolve</code>
 * </dl>
 * <p>As a good beans citizen, these functionalities are
 * observables through specific set of events:
 * <dl>
 * <dt>AttributeChangeEvent
 * <dd>A sub-class of <code>PropertyChangeEvent</code>, allows to track any
 * attribute change. 
 * <dt>StuctureEvent
 * <dd>Allow to track when the resource is loaded, or unloaded from memory.
 * </dl>
 * @see java.beans.Introspector
 * @see java.beans.PropertyChangeEvent
 * @see java.io.Serializable
 */

public interface Resource {

  /**
   * Create that resource and attach it to the given space.
   * A resource is <em>created</em> by calling this method right after
   * the new instance has finished. A resource is always created once,
   * but can be initialized as many times as it is loaded.
   * @param context The context to create the resource.
   * @exception ResourceInitException If the resource cannot be created,
   * either because of invalid default values, or because it cannot be 
   * attached to the space.
   */

  public void create(ResourceContext context)
    throws ResourceInitException;

  /**
   * Destroy that resource, for ever.
   * @exception SecurityException If that access is denied.
   */

  public void destroy();

  /**
   * List all available attribute names of that resource.
   * The DefaultResource relies on the Java reflection API to implement this
   * method. However, one can change that default implementation for 
   * preventing a beans <em>property</em> to be seen as a resource
   * <em>attribute</em>. This would also require changing the default
   * implementation for attribute value accessors.
   * @return An enumeration of PropertyDescriptor instances.
   * @exception SecurityException If that access is denied.
   * @see java.beans.PropertyDescriptor
   */

  public java.util.Enumeration getProperties();

  // Should also supports related events, and provide some documentation
  public void addDelegatee(ResourceReference resource);
  public void removeDelegatee(ResourceReference resource);
  // That's the part of it that will be in Java Beans some days
  public Object getInstanceOf(Class delegateInterface);
  public boolean isInstanceOf(Class delegateInterface);
  public ResourceReference[] getDelegatees();

  /**
   * Get an attribute value.
   * The DefaultResource class provides a default implementation for that
   * method that relies on Java reflection's API (it will search for
   * a <em>name</em> property and invoke its <code>reader</code> method
   * to access the attribute's value.
   * @param name The attribute's name.
   * @return The attribute value, conforming to the type specified
   * by the beans property description.
   * @exception IllegalAccessException If the given attribute is not
   * supported by the resource.
   * @exception SecurityException If that access is denied.
   */
    
  public Object getValue(String name)
    throws IllegalAccessException;

  /**
   * Get a set of attribute values.
   * This version of <code>getValue</code> will fetch simultaneously
   * several property values. It can be thought of as a series of call
   * to the single <code>getValue</code> method, but has two additional 
   * properties:
   * <ul>
   * <li>It is <em>atomic</em>,
   * <li>It is likely to be more efficent.
   * </ul>
   * @param names The set of attribute names whose value is to be fetched.
   * @return An array of values.
   * @exception IllegalAccessException if one of the attribute's name
   * is invalid.
   * @exception SecurityException If that access is denied.
   */

  public Object[] getValues(String names[]) 
    throws IllegalAccessException;

  /**
   * Set an attribute value.
   * The DefaultResource class provides a default implementation for that
   * method by relying on Java reflection's API (see the <code>getValue
   * </code> method description).
   * @param name The name of the attribute whose value is to be changed.
   * @param value The new value for that attribute.
   * @exception IllegalAccessException If the attribuite doesn't exist.
   * @exception IllegalArgumentException If the provided value doesn't
   * work as a value for this attribute.
   * @exception SecurityException If that access is denied.
   */

  public void setValue(String name, Object value) 
    throws IllegalAccessException, IllegalArgumentException;

  /**
   * Set a number of attribute values at once.
   * This bears the same relationship with <code>setValue</code> than
   * <code>getValue</code> to <code>getValues</code>.
   * The changes are guaranteed to be either all performed, or none of them
   * if performed. For efficiency reasons, the provided <em>values</em>
   * parameter <strong>may</strong> be modified by the method.
   * @param names The attribute names,
   * @param values The new values for these attributes.
   * @exception IllegalAccessException If one of the attribute doesn't
   * exist.
   * @exception IllegalArgumentException If one of the value is invalid.
   * @exception SecurityException If that access is denied.
   */

  public void setValues(String names[], Object values[]) 
    throws IllegalAccessException, IllegalArgumentException;

  /**
   * Get the name of that resource.
   * A resource is <strong>required</strong> to have a <em>name</em>.
   * @return The name of the resource, as a String.
   * @exception SecurityException If that access is denied.
   */

  public String getName();

  /**
   * Set the name of that resource.
   * A resource is <strong>required</strong> to have a <em>name</em>.
   * @param name The new name for that resource.
   * @exception SecurityException If that access is denied.
   */

  public void setName(String name);

  /**
   * Resolve the given state.
   * If the state has more components, it is up to the resource to consume
   * the next available component and map it to one of its children, 
   * otherwise the resource must check against whatever security mechanism
   * it uses, wether the access should be granted.
   * @param state The lookup state instance to resolve.
   * @exception SecurityException If that access is denied.
   * @see ResourceSpace
   */

  public ResourceReference resolve(LookupState state);

  /**
   * Initialize that resource within the given context.
   * A resource implementor is <strong>guaranteed</strong> that this method
   * will get called after the instance carries its proper attribute
   * settings and before any other access to the resource is performed.
   * @param context The context in which that resource is to initialize
   * itself.
   * @exception ResourceInitException If the resource is not able to 
   * initialize itself in the given context.
   * @exception SecurityException If that access is denied.
   */

  public void init(ResourceContext context)
    throws ResourceInitException;

  /**
   * Do you want to unload yourself ?
   * Check wether this resource is willing to be persistified back to disk.
   * If the resource agrees to be unloaded, then it should mark itself as
   * no longer valid. The caller is than free to take any appropriate action
   * to unload that resource from memory (provided it can guarantee that no
   * one else in the system is using it).
   * @return A boolean, <strong>true</strong> if the resource can be
   * unloaded <strong>false</strong> otherwise.
   */

  public boolean unload();
    
  /**
   * Add an observer for monitoring attribute changes.
   * @param l The listener to be added.
   * @exception SecurityException If that access is denied.
   * @see AttributeChangeListener
   */

  public void addAttributeChangedListener(AttributeChangedListener l);

  /**
   * Remove an observer for monitoring attribute changes.
   * @param l The listener to remove.
   * @exception SecurityException If that access is denied.
   */

  public void removeAttributeChangedListener(AttributeChangedListener l);

  // added

  public ResourceReference getContainer();

  /**
   * use by specific Saver (ascii for example)
   */
  public void setContainer(ResourceReference container);

  /**
   * use by specific Saver (ascii for example)
   */
  public PropertyHolder getPropertyHolder();

}
