/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.util.ServiceLoader;


/**
 * Adnotacje dodające do kodu informacje o znaczeniu semantycznym.
 * Z niektórych adnotacji bliblioteka może intensywnie korzystać w runtime,
 * inne są tylko podpowiedziami dla programistów i/lub narzędzi sprawdzających
 * kod.
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
@SuppressWarnings("PMD.PackageClass")
public final class Meta {

    private Meta() { }

    /**
     * Pole ma nadawaną wartość tylko raz, ale poza konstruktorem. Na przykład
     * procedurze {@code onInit}, {@code onCreate} lub podobnej.
     */
    @Retention(RUNTIME)
    @Target({FIELD})
    @Documented
    public @interface Final {
        /**
         * Symboliczna nazwa metody, w której następuje inicjalizacja (create, init, show, etc etc)
         * @return default = ""
         */
        String value() default "";

    }
    
    /**
     * The class is immutable. I'ts guaranteed that every method supposed to 
     * change object will throw exception. Ideally, object does not have any
     * method of that kind in public interface.
     * <p>
     * Immutable object most often has all fields final, and use only references
     * to immutable objects. By default, immutable object are thread-safe. 
     * If not, you should change "threadsafe" parameter. 
     * </p>
     * <p> Annotation is especially helpfull if you need to create some subclass 
     * of java collection or implement interface. There is no "ImmutableList" or
     * something like that. Annotation is clean method of expressing your intentions
     * about object's behaviour.
     * </p>
     */
    @Retention(RUNTIME)
    @Target({TYPE})
    @Documented
    public @interface Immutable {

        boolean threadsafe() default true;

    }

    /**
     * <p>
     * Jeśli funkcja z dowolnego powodu wymaga szczególnej ostrożności,
     * to powinna tym być oznaczona. Przykłady zachowań:</p>
     * <ul>
     *      <li>funkcja wykonuje rzutowania "unchecked"</li>
     *      <li>"undefined behaviour" w niektórych warunkach</li>
     *      <li>"expose internal array"</li>
     *      <li>może powodować rece condition</li>
     *      <li>zwraca null zamiast uczciwie rzucać wyjątek</li>
     * </ul>
     */
    @Retention(RUNTIME)
    @Target({TYPE, METHOD, CONSTRUCTOR})
    @Documented
    public @interface Unsafe {
    }

    /**
     * Adnotowana klasa jest implementacją interfejsu obsługiwanego za pomocą
     * {@link ServiceLoader}. Powinien zostać wygenerowany odpowiedni wpis do
     * manifestu pliku JAR.
     */
    @Retention(SOURCE)
    @Documented
    @Target(TYPE)
    public @interface JavaService {
        /**
         * Jeśli klasa implementuje więcej niż jeden interfejs, to należy wskazać
         * interfejs, która powinien zostać wyeksportowany w manifeście.
         * @return
         */
        Class value() default void.class;
    }

}
