001package jmri.jmrit.logixng.implementation;
002
003import java.util.ArrayList;
004import java.util.List;
005import java.util.Map;
006import java.util.HashMap;
007import java.util.ServiceLoader;
008
009import javax.annotation.Nonnull;
010
011import jmri.*;
012import jmri.jmrit.logixng.*;
013import jmri.util.LoggingUtil;
014import jmri.util.ThreadingUtil;
015
016/**
017 * Class providing the basic logic of the DigitalBooleanActionManager interface.
018 *
019 * @author Dave Duchamp       Copyright (C) 2007
020 * @author Daniel Bergqvist   Copyright (C) 2018
021 */
022public class DefaultDigitalBooleanActionManager extends AbstractBaseManager<MaleDigitalBooleanActionSocket>
023        implements DigitalBooleanActionManager {
024
025    private final Map<Category, List<Class<? extends Base>>> actionClassList = new HashMap<>();
026    private MaleSocket _lastRegisteredBean;
027
028
029    public DefaultDigitalBooleanActionManager() {
030        InstanceManager.getDefault(LogixNG_Manager.class).registerManager(this);
031
032        for (DigitalBooleanActionFactory actionFactory : ServiceLoader.load(DigitalBooleanActionFactory.class)) {
033            actionFactory.init();
034        }
035
036        for (Category category : LogixNG_Category.values()) {
037            actionClassList.put(category, new ArrayList<>());
038        }
039
040        for (DigitalBooleanActionFactory actionFactory : ServiceLoader.load(DigitalBooleanActionFactory.class)) {
041            actionFactory.getClasses().forEach((entry) -> {
042//                System.out.format("Add action: %s, %s%n", entry.getKey().name(), entry.getValue().getName());
043                actionClassList.get(entry.getKey()).add(entry.getValue());
044            });
045        }
046
047        for (MaleDigitalBooleanActionSocketFactory maleSocketFactory : ServiceLoader.load(MaleDigitalBooleanActionSocketFactory.class)) {
048            _maleSocketFactories.add(maleSocketFactory);
049        }
050    }
051
052    /** {@inheritDoc} */
053    @Override
054    public Class<? extends MaleSocket> getMaleSocketClass() {
055        return DefaultMaleDigitalBooleanActionSocket.class;
056    }
057
058    protected MaleDigitalBooleanActionSocket createMaleActionSocket(DigitalBooleanActionBean action) {
059        MaleDigitalBooleanActionSocket socket = new DefaultMaleDigitalBooleanActionSocket(this, action);
060        action.setParent(socket);
061        return socket;
062    }
063
064    /** {@inheritDoc} */
065    @Override
066    public MaleSocket getLastRegisteredMaleSocket() {
067        return _lastRegisteredBean;
068    }
069
070    /** {@inheritDoc} */
071    @Override
072    public MaleDigitalBooleanActionSocket registerBean(MaleDigitalBooleanActionSocket maleSocket) {
073        MaleDigitalBooleanActionSocket bean = super.registerBean(maleSocket);
074        _lastRegisteredBean = maleSocket;
075        return bean;
076    }
077
078    /**
079     * Remember a NamedBean Object created outside the manager.
080     * This method creates a MaleDigitalBooleanActionSocket for the action.
081     *
082     * @param action the bean
083     */
084    @Override
085    public MaleDigitalBooleanActionSocket registerAction(@Nonnull DigitalBooleanActionBean action)
086            throws IllegalArgumentException {
087
088        if (action instanceof MaleDigitalBooleanActionSocket) {
089            throw new IllegalArgumentException("registerAction() cannot register a MaleDigitalBooleanActionSocket. Use the method register() instead.");
090        }
091
092        // Check if system name is valid
093        if (this.validSystemNameFormat(action.getSystemName()) != NameValidity.VALID) {
094            log.warn("SystemName {} is not in the correct format", action.getSystemName() );
095            throw new IllegalArgumentException(String.format("System name is invalid: %s", action.getSystemName()));
096        }
097
098        // Keep track of the last created auto system name
099        updateAutoNumber(action.getSystemName());
100
101        // save in the maps
102        MaleDigitalBooleanActionSocket maleSocket = createMaleActionSocket(action);
103        return registerBean(maleSocket);
104    }
105
106    @Override
107    public int getXMLOrder() {
108        return LOGIXNG_DIGITAL_BOOLEAN_ACTIONS;
109    }
110
111    @Override
112    public char typeLetter() {
113        return 'Q';
114    }
115
116    /*.*
117     * Test if parameter is a properly formatted system name.
118     *
119     * @param systemName the system name
120     * @return enum indicating current validity, which might be just as a prefix
121     *./
122    @Override
123    public NameValidity validSystemNameFormat(String systemName) {
124        return LogixNG_Manager.validSystemNameFormat(
125                getSubSystemNamePrefix(), systemName);
126    }
127*/
128    @Override
129    public FemaleDigitalBooleanActionSocket createFemaleSocket(
130            Base parent, FemaleSocketListener listener, String socketName) {
131        return new DefaultFemaleDigitalBooleanActionSocket(parent, listener, socketName);
132    }
133
134    @Override
135    public Map<Category, List<Class<? extends Base>>> getActionClasses() {
136        return actionClassList;
137    }
138
139    /** {@inheritDoc} */
140    @Override
141    public String getBeanTypeHandled(boolean plural) {
142        return Bundle.getMessage(plural ? "BeanNameDigitalBooleanActions" : "BeanNameDigitalBooleanAction");
143    }
144
145    /** {@inheritDoc} */
146    @Override
147    public void deleteDigitalBooleanAction(MaleDigitalBooleanActionSocket x) {
148        // delete the MaleDigitalBooleanActionSocket
149        deregister(x);
150        x.dispose();
151    }
152
153    static volatile DefaultDigitalBooleanActionManager _instance = null;
154
155    @InvokeOnGuiThread  // this method is not thread safe
156    static public DefaultDigitalBooleanActionManager instance() {
157        if (!ThreadingUtil.isGUIThread()) {
158            LoggingUtil.warnOnce(log, "instance() called on wrong thread");
159        }
160
161        if (_instance == null) {
162            _instance = new DefaultDigitalBooleanActionManager();
163        }
164        return (_instance);
165    }
166
167    @Override
168    public Class<MaleDigitalBooleanActionSocket> getNamedBeanClass() {
169        return MaleDigitalBooleanActionSocket.class;
170    }
171
172    @Override
173    protected MaleDigitalBooleanActionSocket castBean(MaleSocket maleSocket) {
174        return (MaleDigitalBooleanActionSocket)maleSocket;
175    }
176
177
178    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultDigitalBooleanActionManager.class);
179
180}