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.InstanceManager;
012import jmri.InvokeOnGuiThread;
013import jmri.jmrit.logixng.*;
014import jmri.util.*;
015
016/**
017 * Class providing the basic logic of the ActionManager interface.
018 * 
019 * @author Dave Duchamp       Copyright (C) 2007
020 * @author Daniel Bergqvist   Copyright (C) 2018
021 */
022public class DefaultAnalogActionManager extends AbstractBaseManager<MaleAnalogActionSocket>
023        implements AnalogActionManager {
024
025    private final Map<Category, List<Class<? extends Base>>> actionClassList = new HashMap<>();
026    private MaleSocket _lastRegisteredBean;
027
028    
029    public DefaultAnalogActionManager() {
030        InstanceManager.getDefault(LogixNG_Manager.class).registerManager(this);
031        
032        for (AnalogActionFactory actionFactory : ServiceLoader.load(AnalogActionFactory.class)) {
033            actionFactory.init();
034        }
035        
036        for (Category category : Category.values()) {
037            actionClassList.put(category, new ArrayList<>());
038        }
039        
040        for (AnalogActionFactory actionFactory : ServiceLoader.load(AnalogActionFactory.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 (MaleAnalogActionSocketFactory maleSocketFactory : ServiceLoader.load(MaleAnalogActionSocketFactory.class)) {
048            _maleSocketFactories.add(maleSocketFactory);
049        }
050    }
051
052    /** {@inheritDoc} */
053    @Override
054    public Class<? extends MaleSocket> getMaleSocketClass() {
055        return DefaultMaleAnalogActionSocket.class;
056    }
057
058    protected MaleAnalogActionSocket createMaleActionSocket(AnalogActionBean action) {
059        MaleAnalogActionSocket socket = new DefaultMaleAnalogActionSocket(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 MaleAnalogActionSocket registerBean(MaleAnalogActionSocket maleSocket) {
073        MaleAnalogActionSocket 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 MaleActionSocket for the action.
081     *
082     * @param action the bean
083     */
084    @Override
085    public MaleAnalogActionSocket registerAction(@Nonnull AnalogActionBean action)
086            throws IllegalArgumentException {
087        
088        if (action instanceof MaleAnalogActionSocket) {
089            throw new IllegalArgumentException("registerAction() cannot register a MaleAnalogActionSocket. 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        MaleAnalogActionSocket maleSocket = createMaleActionSocket(action);
102        return registerBean(maleSocket);
103    }
104    
105    @Override
106    public int getXMLOrder() {
107        return LOGIXNG_ANALOG_ACTIONS;
108    }
109
110    @Override
111    public String getBeanTypeHandled() {
112        return Bundle.getMessage("BeanNameAnalogAction");
113    }
114
115    /** {@inheritDoc} */
116    @Override
117    public void deleteAnalogAction(MaleAnalogActionSocket x) {
118        // delete the MaleAnalogActionSocket
119        deregister(x);
120        x.dispose();
121    }
122
123    @Override
124    public char typeLetter() {
125        return 'Q';
126    }
127
128    /*.*
129     * Test if parameter is a properly formatted system name.
130     *
131     * @param systemName the system name
132     * @return enum indicating current validity, which might be just as a prefix
133     *./
134    @Override
135    public NameValidity validSystemNameFormat(String systemName) {
136        return LogixNG_Manager.validSystemNameFormat(
137                getSubSystemNamePrefix(), systemName);
138    }
139*/
140    @Override
141    public FemaleAnalogActionSocket createFemaleSocket(
142            Base parent, FemaleSocketListener listener, String socketName) {
143        return new DefaultFemaleAnalogActionSocket(parent, listener, socketName);
144    }
145
146    @Override
147    public Map<Category, List<Class<? extends Base>>> getActionClasses() {
148        return actionClassList;
149    }
150
151    /** {@inheritDoc} */
152    @Override
153    public String getBeanTypeHandled(boolean plural) {
154        return Bundle.getMessage(plural ? "BeanNameAnalogActions" : "BeanNameAnalogAction");
155    }
156    
157    static volatile DefaultAnalogActionManager _instance = null;
158
159    @InvokeOnGuiThread  // this method is not thread safe
160    static public DefaultAnalogActionManager instance() {
161        if (!ThreadingUtil.isGUIThread()) {
162            LoggingUtil.warnOnce(log, "instance() called on wrong thread");
163        }
164        
165        if (_instance == null) {
166            _instance = new DefaultAnalogActionManager();
167        }
168        return (_instance);
169    }
170
171    @Override
172    public Class<MaleAnalogActionSocket> getNamedBeanClass() {
173        return MaleAnalogActionSocket.class;
174    }
175
176    @Override
177    protected MaleAnalogActionSocket castBean(MaleSocket maleSocket) {
178        return (MaleAnalogActionSocket)maleSocket;
179    }
180
181
182    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultAnalogActionManager.class);
183
184}