import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/** Simulasi resolusi modul jlink: closure graf requires dari sekumpulan modul akar. */
public class GrafModul {

    /** Graf requires modul JDK 25 (disalin dari java --describe-module). */
    static final Map<String, List<String>> REQUIRES = Map.of(
            "java.sql", List.of("java.logging", "java.transaction.xa", "java.xml"),
            "java.logging", List.of(),
            "java.transaction.xa", List.of(),
            "java.xml", List.of(),
            "java.net.http", List.of(),
            "java.management", List.of());

    /** Closure ala jlink: berangkat dari modul akar, ikuti semua edge requires.
     *  java.base selalu disertakan karena sifatnya mandated. */
    static Set<String> resolusi(String... akar) {
        Set<String> hasil = new TreeSet<>(); // TreeSet -> urutan cetak deterministik
        hasil.add("java.base");
        Deque<String> antrean = new ArrayDeque<>(List.of(akar));
        while (!antrean.isEmpty()) {
            String m = antrean.poll();
            if (hasil.add(m)) {
                antrean.addAll(REQUIRES.getOrDefault(m, List.of()));
            }
        }
        return hasil;
    }

    static void laporan(String judul, Set<String> modul) {
        System.out.println("== " + judul + " ==");
        System.out.println("jumlah modul runtime: " + modul.size());
        for (String m : modul) {
            System.out.println("  " + m);
        }
        System.out.println();
    }

    public static void main(String[] args) {
        System.out.println("JDK lengkap terpasang: 69 modul (java --list-modules)");
        System.out.println();

        laporan("jlink --add-modules java.sql", resolusi("java.sql"));
        laporan("jlink --add-modules java.net.http", resolusi("java.net.http"));
        laporan("jlink --add-modules java.sql,java.management",
                resolusi("java.sql", "java.management"));
    }
}
