001package jmri.jmrit.withrottle;
002
003import java.util.ArrayList;
004import java.util.List;
005
006/**
007 * Abstract for controllers that want to receive or send communications to a
008 * connected wi-fi device.
009 *
010 *
011 * @author Brett Hoffman Copyright (C) 2010
012 */
013abstract public class AbstractController {
014
015    ArrayList<ControllerInterface> listeners = null;
016    List<String> sysNameList = null;
017
018    boolean isValid = false;
019    boolean canBuildList = true;
020
021    /**
022     * isValid is used to indicate if the Controller is created. If false, we
023     * can null the controller and reduce overhead.
024     *
025     * @return isValid
026     */
027    abstract boolean verifyCreation();
028
029    /**
030     * Break down a message and use it.
031     * @param message message for controller to parse and take action
032     * @param deviceServer DeviceServer that sent this message, used to send response messages to proper client
033     *
034     */
035    abstract void handleMessage(String message, DeviceServer deviceServer);
036
037    /**
038     * Register as listener of NamedBeans to be updated of changes.
039     */
040    abstract void register();
041
042    /**
043     * Deregister as listener of NamedBeans
044     */
045    abstract void deregister();
046
047    /**
048     * Build list only if there are no controller listeners. This way the list
049     * is not changed while in use. This should only be called by a subclass of
050     * jmri.Manager *Manager can implement specifics in register().
051     * @param manager which manager to get system names for.
052     *
053     */
054    public void buildList(jmri.Manager<?> manager) {
055        if (sysNameList == null) {
056            sysNameList = new ArrayList<>(manager.getNamedBeanSet().size());
057            manager.getNamedBeanSet().forEach(bean -> {
058                sysNameList.add(bean.getSystemName());
059            });
060            filterList();   //  To remove unwanted objects
061            register();
062            canBuildList = false;
063        }
064
065    }
066
067    public void filterList() {
068        //  Override to filter by wifiControlled field of turnout or route object.
069    }
070
071    /**
072     * If no listeners, clear sysNameList pointer and allow list to be re-built
073     *Manager can implement specifics in deregister().
074     */
075    public void checkCanBuildList() {
076        if (listeners.isEmpty()) {
077            if (sysNameList != null) {
078                deregister();
079                sysNameList = null;
080            }
081            canBuildList = true;
082        }
083    }
084
085    /**
086     * Add a listener to handle: listener.sendPacketToDevice(message);
087     * @param listener listener to add to listeners list
088     */
089    public void addControllerListener(ControllerInterface listener) {
090        if (listeners == null) {
091            listeners = new ArrayList<>(1);
092        }
093        if (!listeners.contains(listener)) {
094            listeners.add(listener);
095        }
096    }
097
098    public void removeControllerListener(ControllerInterface listener) {
099        if (listeners == null) {
100            return;
101        }
102        if (listeners.contains(listener)) {
103            listeners.remove(listener);
104        }
105        checkCanBuildList();
106    }
107
108}