/**
 * @file ovm/core/domain/Method.java
 **/
package ovm.core.domain;

import ovm.core.repository.Mode;
import ovm.core.repository.Selector;
import ovm.core.repository.Bytecode;
import ovm.core.repository.RepositoryMember;
import ovm.util.NoSuchElementException;

/**
 * The interface for <code>Method</code> objects. This object should contain
 * modifier information, selector, declaring type, return type, thrown
 * exception types, argument types, and any other information 
 * that needs to be associated with the specific method object.
 **/
public interface Method extends Member {
    /**
     * Return an integer that uniquely identifiers this method
     * within it's Type.Context (as returned by
     * getDeclaringType().getContext()).
     **/
    int getUID();

    /**
     * Return the unique identifier for a blueprint's context.
     * This is equivalent to getDeclaringType().getContext().getUID(),
     * and the (CID,UID) pair uniquely identifies a method.
     **/
    int getCID();

    boolean isConstructor();
    boolean isClassInit();
    
    boolean isNonVirtual();
    boolean isVirtual();
    boolean isInterface();
    /**
     * Get the bound selector object for this method
     * @return this method's bound selector
     **/
    Selector.Method getSelector();
    /**
     * Get the modifiers object for this method
     * @return this method's mode object
     **/
    Mode.Method getMode();
    /**
     * Get the <code>Type</code> object for the return type associated with 
     * this method
     * @return this method's return <code>Type</code>
     **/
    Type getReturnType() throws LinkageException;
    /**
     * Get the <code>Type</code> for the exceptions thrown by this method
     * @return this method's thrown exception <code>Type</code>
     **/
    Type.Class getThrownType(int i) throws LinkageException;
    /**
     * Get the number of  exceptions thrown by this method
     **/
    int getThrownTypeCount();
    /**
     * Get the <code>Type</code> for the <code>i</code>th argument of this method 
     * @return this method's argument <code>Types</code>
     **/
    Type getArgumentType(int i) throws LinkageException;
    /**
     * Get the number of arguments this method takes (excluding this)
     **/
    int getArgumentCount();
    /**
     * FIXME convert to sth like getOriginalCode() since the distributed
     * format doesn't have to be this
     **/
    Bytecode getOriginalByteCode();

    /**
     * Get the (unlinked) repository representation of this method.
     **/
    RepositoryMember.Method getRepositoryMethod();

    /**
     * Given a kind give the bytecode/native/whatever code for it in
     * form of a byte array.
     **/
    Code getCode(Code.Kind kind);

    void addCode(Code code);
    /**
     * Iterator interface for <code>Method</code> objects
     **/
    interface Iterator {
	/**
	 * Determine if there is a next element in the sequence
	 * @return true if there else a next element, false if not
	 **/
	public boolean hasNext();
	/**
	 * Get the next element in the sequence
	 * @return the next <code>Method</code> in the sequence.
	 **/
	public Method next();

        final Iterator EMPTY_INSTANCE = new Iterator() {
            public boolean hasNext() { return false; }
            public Method next() { throw new NoSuchElementException(); }
        };
    }
}
