import java.lang.annotation.*;
import java.lang.reflect.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@interface Fungsional {}   // hanya untuk deklarasi tipe dan method

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface KunciUtama {}   // hanya untuk field

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CONSTRUCTOR)
@interface DibangunOleh {} // hanya untuk constructor

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@interface Divalidasi {}   // hanya untuk parameter method

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.RECORD_COMPONENT)
@interface Terindeks {}    // hanya untuk komponen record

@Retention(RetentionPolicy.RUNTIME)
@interface Bebas {}        // tanpa @Target: boleh di mana saja

@Fungsional
@Bebas
class Katalog {
    @KunciUtama
    private String kode;

    @DibangunOleh
    public Katalog() {}

    @Fungsional
    public void tampil() {}

    public void simpan(@Divalidasi @Bebas String kode) {
        this.kode = kode;
    }
}

record Buku(@Terindeks String judul) {}

public class ContohTarget {
    public static void main(String[] args) throws Exception {
        System.out.println("@Fungsional di class Katalog : "
                + (Katalog.class.getAnnotation(Fungsional.class) != null));

        Field kode = Katalog.class.getDeclaredField("kode");
        System.out.println("@KunciUtama di field kode    : "
                + (kode.getAnnotation(KunciUtama.class) != null));

        Constructor<?> ctor = Katalog.class.getDeclaredConstructor();
        System.out.println("@DibangunOleh di constructor : "
                + (ctor.getAnnotation(DibangunOleh.class) != null));

        Method simpan = Katalog.class.getDeclaredMethod("simpan", String.class);
        Annotation[][] param = simpan.getParameterAnnotations();
        System.out.println("@Divalidasi di parameter     : "
                + (param.length > 0 && param[0].length > 0));

        RecordComponent rc = Buku.class.getRecordComponents()[0];
        System.out.println("@Terindeks di record judul   : "
                + (rc.getAnnotation(Terindeks.class) != null));
    }
}
