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