package java.lang.annotation;

import ej.annotation.Nullable;

/**
 * The common interface extended by all annotation types. Note that an interface that manually
 * extends this one does <i>not</i> define an annotation type. Also note that this interface does
 * not itself define an annotation type.
 *
 * More information about annotation types can be found in section 9.6 of <cite>The Java&trade;
 * Language Specification</cite>.
 */
public interface Annotation {

	/**
	 * Returns the annotation type of this annotation.
	 * @return the annotation type of this annotation.
	 */
	Class<? extends Annotation> annotationType();

	/**
	 * Returns true if the specified object represents an annotation that is logically equivalent to
	 * this one. In other words, returns true if the specified object is an instance of the same
	 * annotation type as this instance, all of whose members are equal to the corresponding member of
	 * this annotation, as defined below:
	 * <ul>
	 * <li>Two corresponding primitive typed members whose values are <code>x</code> and <code>y</code> are
	 * considered equal if <code>x == y</code>, unless their type is <code>float</code> or <code>double</code>.
	 *
	 * <li>Two corresponding <code>float</code> members whose values are <code>x</code> and <code>y</code> are
	 * considered equal if <code>Float.valueOf(x).equals(Float.valueOf(y))</code>. (Unlike the <code>==</code>
	 * operator, NaN is considered equal to itself, and <code>0.0f</code> unequal to <code>-0.0f</code>.)
	 *
	 * <li>Two corresponding <code>double</code> members whose values are <code>x</code> and <code>y</code> are
	 * considered equal if <code>Double.valueOf(x).equals(Double.valueOf(y))</code>. (Unlike the <code>==</code>
	 * operator, NaN is considered equal to itself, and <code>0.0</code> unequal to <code>-0.0</code>.)
	 *
	 * <li>Two corresponding <code>String</code>, <code>Class</code>, enum, or annotation typed members whose
	 * values are <code>x</code> and <code>y</code> are considered equal if <code>x.equals(y)</code>. (Note that
	 * this definition is recursive for annotation typed members.)
	 * </ul>
	 * @return true if the specified object represents an annotation that is logically equivalent to
	 *         this one, otherwise false
	 */
	@Override
	boolean equals(@Nullable Object obj);

	/**
	 * Returns the hash code of this annotation, as defined below:
	 *
	 * <p>
	 * The hash code of an annotation is the sum of the hash codes of its members (including those with
	 * default values), as defined below:
	 *
	 * The hash code of an annotation member is (127 times the hash code of the member-name as computed
	 * by {@link String#hashCode()}) XOR the hash code of the member-value, as defined below:
	 *
	 * <p>
	 * The hash code of a member-value depends on its type:
	 * <ul>
	 * <li>The hash code of a primitive value <code><i>v</i></code> is equal to
	 * <code><i>WrapperType</i>.valueOf(<i>v</i>).hashCode()</code>, where <code><i>WrapperType</i></code> is
	 * the wrapper type corresponding to the primitive type of <code><i>v</i></code> ({@link Byte},
	 * {@link Character}, {@link Double}, {@link Float}, {@link Integer}, {@link Long}, {@link Short},
	 * or {@link Boolean}).
	 *
	 * <li>The hash code of a string, enum, class, or annotation member-value I <code><i>v</i></code> is
	 * computed as by calling <code><i>v</i>.hashCode()</code>. (In the case of annotation member values,
	 * this is a recursive definition.)
	 * </ul>
	 *
	 * @return the hash code of this annotation
	 */
	@Override
	int hashCode();

	/**
	 * Returns a string representation of this annotation. The details of the representation are
	 * implementation-dependent, but the following may be regarded as typical:
	 *
	 * <pre>
	 *   &#064;com.acme.util.Name(first=Alfred, middle=E., last=Neuman)
	 * </pre>
	 *
	 * @return a string representation of this annotation
	 */
	@Override
	String toString();
}
