package io.gitlab.jfronny.inceptum.launcher.system.instance; import io.gitlab.jfronny.inceptum.launcher.model.inceptum.GC_InstanceMeta; import io.gitlab.jfronny.commons.io.JFiles; import io.gitlab.jfronny.commons.throwable.ThrowingConsumer; import io.gitlab.jfronny.commons.throwable.ThrowingRunnable; import io.gitlab.jfronny.inceptum.common.MetaHolder; import io.gitlab.jfronny.inceptum.common.Utils; import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta; import io.gitlab.jfronny.inceptum.launcher.util.FileBackedRef; import java.io.Closeable; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; import java.util.stream.Stream; public class InstanceList { private static final Map metas = new LinkedHashMap<>(); public static void lock(ThrowingRunnable task) throws TEx { synchronized (metas) { task.run(); } } public static void reset() { synchronized (metas) { for (var entry : metas.entrySet()) { try { entry.getValue().close(); } catch (IOException e) { Utils.LOGGER.error("Could not close reference to instance meta", e); } } metas.clear(); } } public static Set ordered() throws IOException { TreeSet set = new TreeSet<>(); forEach(set::add); return set.descendingSet(); } public static void forEach(ThrowingConsumer target) throws IOException, TEx { Objects.requireNonNull(target); if (!Files.exists(MetaHolder.INSTANCE_DIR)) Files.createDirectories(MetaHolder.INSTANCE_DIR); try { JFiles.listTo(MetaHolder.INSTANCE_DIR, path -> { if (!isInstance(path)) return; target.accept(read(path)); }); } catch (Exception e) { //noinspection unchecked throw (TEx) e; } } public static boolean isEmpty() throws IOException { if (!Files.exists(MetaHolder.INSTANCE_DIR)) return true; return JFiles.list(MetaHolder.INSTANCE_DIR, InstanceList::isInstance).isEmpty(); } public static int size() throws IOException { if (!Files.exists(MetaHolder.INSTANCE_DIR)) return 0; try (Stream list = Files.list(MetaHolder.INSTANCE_DIR)) { return (int) list.filter(InstanceList::isInstance).count(); } } public static Instance read(Path instancePath) throws IOException { Objects.requireNonNull(instancePath); synchronized (metas) { if (!metas.containsKey(instancePath)) { metas.put(instancePath, new IEntry( instancePath, new FileBackedRef<>(instancePath.resolve(Instance.CONFIG_NAME), GC_InstanceMeta::read) )); } return metas.get(instancePath).toPub(); } } private static boolean isInstance(Path path) { return Files.isDirectory(path) && Files.exists(path.resolve(Instance.CONFIG_NAME)); } private record IEntry(Path path, FileBackedRef meta) implements Closeable { @Override public String toString() { return path.getFileName().toString(); } public Instance toPub() throws IOException { return new Instance(path, meta.get()); } @Override public void close() throws IOException { meta.close(); } } }