package de.steamwar.command; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.experimental.UtilityClass; import java.util.*; import java.util.function.Supplier; @UtilityClass public class TabCompletionCache { private Map tabCompletionCache = new HashMap<>(); Set> cached = new HashSet<>(); Set> global = new HashSet<>(); Map, Long> cacheDuration = new HashMap<>(); void add(AbstractTypeMapper typeMapper, AbstractSWCommand.Cached cached) { if (cached != null) { TabCompletionCache.cached.add(typeMapper); if (cached.global()) TabCompletionCache.global.add(typeMapper); TabCompletionCache.cacheDuration.put(typeMapper, cached.timeUnit().toMillis(cached.cacheDuration())); } } @EqualsAndHashCode @AllArgsConstructor private static class Key { private Object sender; private AbstractTypeMapper typeMapper; } @AllArgsConstructor private static class TabCompletions { private AbstractSWCommand command; private long timestamp; private Collection tabCompletions; } Collection tabComplete(Object sender, AbstractTypeMapper typeMapper, AbstractSWCommand command, Supplier> tabCompleteSupplier) { if (!cached.contains(typeMapper)) return tabCompleteSupplier.get(); Key key = global.contains(typeMapper) ? new Key(null, typeMapper) : new Key(sender, typeMapper); TabCompletions tabCompletions = tabCompletionCache.computeIfAbsent(key, ignore -> { return new TabCompletions(command, System.currentTimeMillis(), tabCompleteSupplier.get()); }); if (tabCompletions.command != command || System.currentTimeMillis() - tabCompletions.timestamp > cacheDuration.get(typeMapper)) { tabCompletions = new TabCompletions(command, System.currentTimeMillis(), tabCompleteSupplier.get()); tabCompletionCache.put(key, tabCompletions); } tabCompletions.timestamp = System.currentTimeMillis(); return tabCompletions.tabCompletions; } public void invalidateOldEntries() { Set toRemove = new HashSet<>(); for (Map.Entry tabCompletionsEntry : tabCompletionCache.entrySet()) { if (System.currentTimeMillis() - tabCompletionsEntry.getValue().timestamp > cacheDuration.get(tabCompletionsEntry.getKey().typeMapper)) { toRemove.add(tabCompletionsEntry.getKey()); } } for (Key key : toRemove) { tabCompletionCache.remove(key); } } }