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