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