001package org.intellimate.izou.system.file;
002
003import org.intellimate.izou.util.IdentificationSet;
004import org.intellimate.izou.util.IzouModule;
005import org.intellimate.izou.identification.Identification;
006import org.intellimate.izou.identification.IllegalIDException;
007import org.intellimate.izou.main.Main;
008
009import java.util.HashMap;
010import java.util.concurrent.CompletableFuture;
011
012/**
013 * FilePublisher that notifies {@link FileSubscriber} objects. It is triggered when a file is reloaded. Particularly
014 * file subscribers are mapped to {@link ReloadableFile} objects. When a reloadable file is reloaded, all file
015 * subscribers belonging to it are notified. All file subscribers in general can also be notified.
016 */
017public class FilePublisher extends IzouModule {
018    private HashMap<ReloadableFile, IdentificationSet<FileSubscriber>> fileSubscribers;
019    private IdentificationSet<FileSubscriber> defaultFileSubscribers;
020
021    /**
022     * Creates a new FilePublisher object. There should only be one in Izou
023     * @param main an Instance of main, used to get all the other classes
024     */
025    public FilePublisher(Main main) {
026        super(main);
027        this.fileSubscribers = new HashMap<>();
028        this.defaultFileSubscribers = new IdentificationSet<>(false);
029    }
030
031    /**
032     * Registers a {@link FileSubscriber} with a {@link ReloadableFile}. So when the {@code reloadableFile} is reloaded,
033     * the fileSubscriber will be notified. Multiple file subscribers can be registered with the same reloadable file.
034     *
035     * @param reloadableFile the reloadable file that should be observed
036     * @param fileSubscriber the fileSubscriber that should be notified when the reloadable file is reloaded
037     * @param identification the Identification of the FileSubscriber
038     * @throws IllegalIDException not yet implemented
039     */
040    public void register(ReloadableFile reloadableFile, FileSubscriber fileSubscriber, Identification identification)
041                                                                                            throws IllegalIDException {
042        IdentificationSet<FileSubscriber> subscribers = fileSubscribers.get(reloadableFile);
043
044        if (subscribers == null) {
045            subscribers = new IdentificationSet<>(false);
046            fileSubscribers.put(reloadableFile, subscribers);
047        }
048        subscribers.add(fileSubscriber, identification);
049    }
050
051    /**
052     * Registers a {@link FileSubscriber} so that whenever any file is reloaded, the fileSubscriber is notified.
053     *
054     * @param fileSubscriber the fileSubscriber that should be notified when the reloadable file is reloaded
055     * @param identification the Identification of the FileSubscriber
056     * @throws IllegalIDException not yet implemented
057     */
058    public void register(FileSubscriber fileSubscriber, Identification identification) throws IllegalIDException {
059        defaultFileSubscribers.add(fileSubscriber, identification);
060    }
061
062    /**
063     * Unregisters all instances of fileSubscriber found.
064     *
065     * @param fileSubscriber the fileSubscriber to unregister
066     */
067    public void unregister(FileSubscriber fileSubscriber) {
068        for (IdentificationSet<FileSubscriber> subList : fileSubscribers.values()) {
069            subList.remove(fileSubscriber);
070        }
071        defaultFileSubscribers.remove(fileSubscriber);
072    }
073
074    /**
075     * Notifies all file subscribers registered to {@code reloadableFile}
076     *
077     * @param reloadableFile the ReloadableFile object for which to notify all pertaining file subscribers
078     */
079    public synchronized void notifyFileSubscribers(ReloadableFile reloadableFile) {
080        notifyDefaultFileSubscribers();
081
082        IdentificationSet<FileSubscriber> subList = fileSubscribers.get(reloadableFile);
083        if (subList == null) {
084            return;
085        }
086
087        for (FileSubscriber sub : subList) {
088            CompletableFuture.runAsync(sub::update, main.getThreadPoolManager().getAddOnsThreadPool());
089        }
090    }
091
092    /**
093     * Notifies all file subscribers.
094     */
095    public synchronized void notifyAllFileSubcribers() {
096        for (IdentificationSet<FileSubscriber> subList : fileSubscribers.values()) {
097            for (FileSubscriber sub : subList) {
098                CompletableFuture.runAsync(sub::update, main.getThreadPoolManager().getAddOnsThreadPool());
099            }
100        }
101
102        notifyDefaultFileSubscribers();
103    }
104
105    /**
106     * Notifies all default file subscribers, that is those that will all be notified no matter what.
107     */
108    public synchronized void notifyDefaultFileSubscribers() {
109        for (FileSubscriber sub : defaultFileSubscribers) {
110            CompletableFuture.runAsync(sub::update, main.getThreadPoolManager().getAddOnsThreadPool());
111        }
112    }
113
114    /**
115     * Get all subscribers for a {@code reloadableFile}
116     *
117     * @param reloadableFile the {@code reloadableFile} for which to get all subscribers
118     * @return all subscribers for a {@code reloadableFile}
119     */
120    public IdentificationSet<FileSubscriber> getFileSubscribersForReloadableFile(ReloadableFile reloadableFile) {
121        return fileSubscribers.get(reloadableFile);
122    }
123}