// $Id: OperationFactory.java,v 1.5 1998/02/05 14:05:06 oliva Exp $

package BR.unicamp.Guarana;

import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/** The object used to create Operations from the meta-level.  The
    only way for a meta-level object to create an Operation for the
    base-leve Objects it reflects on is through an OperationFactory.
    Such objects are distributed at MetaObject initialize time; any
    MetaObject that may intend to create Operations must store a
    reference to this Object.

    <p>An instance of this class may refuse to create certain
    Operations, thus limiting the access a MetaObject may have to the
    base Object.  In particular, as soon as the MetaObject directly
    associated with an Object is replaced, the OperationFactory
    previously distributed to the components of the former
    meta-configuration will refuse to create any Operation.  A new
    valid OperationFactory is given to all the components of the new
    meta-configuration just before it starts handling Operations.

    @see MetaObject#initialize

    @author Alexandre Oliva
    @version $Revision: 1.5 $ */
public abstract class OperationFactory {
  /** Should return the Object this OperationFactory creates
      Operations for.  For static Operations, it will be the target
      class.

      @return the target Object for this class.  */
  public abstract Object getObject();

  /** Creates a Method invocation Operation.  Actually, it just calls
      the other version of this method, with an additional null
      Operation argument.

      @param method the Method to be invoked.

      @param arguments the argument list to be passed to the Method.

      @return the new Operation.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public final Operation invoke(final Method method,
				final Object[] arguments)
    throws IllegalAccessException {
    return invoke(method, arguments, null);
  }

  /** Creates a Constructor invocation Operation.  Actually, it just
      calls the other version of this method, with an additional null
      Operation argument.

      @param constructor the Constructor to be invoked.

      @param arguments the argument list to be passed to the
      Constructor.

      @return the new Operation.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public final Operation construct(final Constructor constructor,
				   final Object[] arguments)
    throws IllegalAccessException {
    return construct(constructor, arguments, null);
  }
  
  /** Creates a start-of-synchronization Operation.  Actually, it just
      calls the other version of this method, with an additional null
      Operation argument.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public final Operation monitorEnter()
    throws IllegalAccessException {
    return monitorEnter(null);
  }

  /** Creates an end-of-synchronization Operation.  Actually, it just
      calls the other version of this method, with an additional null
      Operation argument.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public final Operation monitorExit()
    throws IllegalAccessException {
    return monitorExit(null);
  }

  /** Creates a Field read Operation.  Actually, it just calls the
      other version of this method, with an additional null Operation
      argument.

      @param field the Field whose value is to be obtained.

      @return the new Operation.  

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public final Operation read(final Field field)
    throws IllegalAccessException {
    return read(field, null);
  }

  /** Creates a Field write Operation.  Actually, it just calls the
      other version of this method, with an additional null Operation
      argument.

      @param field the Field whose value is to be changed.

      @param value the value to be stored in the Field.

      @return the new Operation.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public final Operation write(final Field field,
			       final Object value)
    throws IllegalAccessException {
    return write(field, value, null);
  }

  /** Creates an Array length Operation.  Actually, it just calls the
      other version of this method, with an additional null Operation
      argument.

      @return the new Operation.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public final Operation length()
    throws IllegalAccessException {
    return length(null);
  }

  /** Creates an Array element read Operation.  Actually, it just
      calls the other version of this method, with an additional null
      Operation argument.

      @param element the element whose value is to be obtained.

      @return the new Operation.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public final Operation readElement(final int element)
    throws IllegalAccessException {
    return readElement(element, null);
  }

  /** Creates an Array element write Operation.  Actually, it just
      calls the other version of this method, with an additional null
      Operation argument.

      @param element the element whose value is to be changed.

      @param value the value to be stored in the element.

      @return the new Operation.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public final Operation writeElement(final int element,
				      final Object value)
    throws IllegalAccessException {
    return writeElement(element, value, null);
  }

  /** Creates a Method invocation Operation.

      @param method the Method to be invoked.

      @param arguments the argument list to be passed to the Method.

      @param operation an Operation that should be replaced.  If it is
      null, a non-replacement Operation is created.
      
      @return the new Operation.

      @exception IllegalArgumentException if the Method return type
      is not compatible with the expected type of the replaced
      Operation.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public abstract Operation invoke(final Method method,
				   final Object[] arguments,
				   final Operation operation)
    throws IllegalArgumentException, IllegalAccessException;

  /** Creates a Constructor invocation Operation.

      @param constructor the Constructor to be invoked.

      @param arguments the argument list to be passed to the
      Constructor.

      @param operation an Operation that should be replaced.  If it is
      null, a non-replacement Operation is created.
      
      @return the new Operation.

      @exception IllegalArgumentException if the expected type of the
      replaced Operation is not void.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public abstract Operation construct(final Constructor constructor,
				      final Object[] arguments,
				      final Operation operation)
    throws IllegalArgumentException, IllegalAccessException;

  /** Creates a start-of-synchronization Operation.

      @param operation an Operation that should be replaced.  If it
      is null, a non-replacement Operation is created.
      
      @return the new Operation.

      @exception IllegalArgumentException if the expected type of the
      replaced Operation is not void.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public abstract Operation monitorEnter(final Operation operation)
    throws IllegalArgumentException, IllegalAccessException;

  /** Creates a replacement end-of-synchronization Operation.

      @param operation an Operation that should be replaced.  If it is
      null, a non-replacement Operation is created.
      
      @return the new Operation.

      @exception IllegalArgumentException if the expected type of the
      replaced Operation is not void.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public abstract Operation monitorExit(final Operation operation)
    throws IllegalArgumentException, IllegalAccessException;

  /** Creates a Field read Operation.

      @param field the Field whose value is to be obtained.

      @param operation an Operation that should be replaced.  If it is
      null, a non-replacement Operation is created.
      
      @return the new Operation.
      
      @exception IllegalArgumentException if the Field type is not
      compatible with the expected Result type of the replaced
      Operation.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public abstract Operation read(final Field field,
				 final Operation operation)
    throws IllegalArgumentException, IllegalAccessException;

  /** Creates a Field write Operation.

      @param field the Field whose value is to be changed.

      @param value the value to be stored in the Field.

      @param operation an Operation that should be replaced.  If it is
      null, a non-replacement Operation is created.
      
      @return the new Operation.

      @exception IllegalArgumentException if the replaced Operation
      did not have type void.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public abstract Operation write(final Field field,
				  final Object value,
				  final Operation operation)
    throws IllegalArgumentException, IllegalAccessException;

  /** Creates an Array length Operation.

      @param operation an Operation that should be replaced.  If it is
      null, a non-replacement Operation is created.
      
      @return the new Operation.

      @exception IllegalArgumentException if the replaced Operation
      did not have type int.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public abstract Operation length(final Operation operation)
    throws IllegalArgumentException, IllegalAccessException;

  /** Creates an Array element read Operation.

      @param element the element whose value is to be obtained.

      @param operation an Operation that should be replaced.  If it is
      null, a non-replacement Operation is created.
      
      @return the new Operation.
      
      @exception IllegalArgumentException if the element type is not
      compatible with the expected type of the replaced Operation.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public abstract Operation readElement(final int element,
					final Operation operation)
    throws IllegalArgumentException, IllegalAccessException;

  /** Creates an Array element write Operation.

      @param element the element whose value is to be changed.

      @param value the value to be stored in the element.

      @param operation an Operation that should be replaced.  If it is
      null, a non-replacement Operation is created.
      
      @return the new Operation.

      @exception IllegalArgumentException if the replaced Operation
      did not have type void.

      @exception IllegalAccessException if the OperationFactory
      refuses to create the requested Operation.  */
  public abstract Operation writeElement(final int element,
					 final Object value,
					 final Operation operation)
    throws IllegalArgumentException, IllegalAccessException;
}
