001package jmri.jmrit.logixng.expressions;
002
003import java.util.Locale;
004import java.util.Map;
005
006import jmri.InstanceManager;
007import jmri.JmriException;
008import jmri.jmrit.logixng.Base;
009import jmri.jmrit.logixng.Category;
010import jmri.jmrit.logixng.FemaleSocket;
011import jmri.jmrit.logixng.FemaleSocketListener;
012import jmri.jmrit.logixng.DigitalExpressionManager;
013import jmri.jmrit.logixng.FemaleDigitalExpressionSocket;
014import jmri.jmrit.logixng.MaleSocket;
015import jmri.jmrit.logixng.SocketAlreadyConnectedException;
016
017/**
018 * An Expression that negates the result of its child expression.
019 * 
020 * This expression returns False if the child returns True. It returns True
021 * if the child returns False. It returns False if no child is connected.
022 * 
023 * @author Daniel Bergqvist Copyright 2021
024 */
025public class Not extends AbstractDigitalExpression implements FemaleSocketListener {
026
027    private String _socketSystemName;
028    private final FemaleDigitalExpressionSocket _socket;
029    
030    public Not(String sys, String user)
031            throws BadUserNameException, BadSystemNameException {
032        
033        super(sys, user);
034        
035        _socket = InstanceManager.getDefault(DigitalExpressionManager.class)
036                .createFemaleSocket(this, this, Bundle.getMessage("Not_SocketName"));
037    }
038    
039    @Override
040    public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws JmriException {
041        DigitalExpressionManager manager = InstanceManager.getDefault(DigitalExpressionManager.class);
042        String sysName = systemNames.get(getSystemName());
043        String userName = userNames.get(getSystemName());
044        if (sysName == null) sysName = manager.getAutoSystemName();
045        Not copy = new Not(sysName, userName);
046        copy.setComment(getComment());
047        return manager.registerExpression(copy).deepCopyChildren(this, systemNames, userNames);
048    }
049    
050    /** {@inheritDoc} */
051    @Override
052    public Category getCategory() {
053        return Category.COMMON;
054    }
055    
056    /** {@inheritDoc} */
057    @Override
058    public boolean evaluate() throws JmriException {
059        return !_socket.evaluate();
060    }
061    
062    @Override
063    public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException {
064        switch (index) {
065            case 0:
066                return _socket;
067                
068            default:
069                throw new IllegalArgumentException(
070                        String.format("index has invalid value: %d", index));
071        }
072    }
073
074    @Override
075    public int getChildCount() {
076        return 1;
077    }
078    
079    @Override
080    public void connected(FemaleSocket socket) {
081        if (socket == _socket) {
082            _socketSystemName = socket.getConnectedSocket().getSystemName();
083        } else {
084            throw new IllegalArgumentException("unkown socket");
085        }
086    }
087    
088    @Override
089    public void disconnected(FemaleSocket socket) {
090        if (socket == _socket) {
091            _socketSystemName = null;
092        } else {
093            throw new IllegalArgumentException("unkown socket");
094        }
095    }
096    
097    @Override
098    public String getShortDescription(Locale locale) {
099        return Bundle.getMessage(locale, "Not_Short");
100    }
101    
102    @Override
103    public String getLongDescription(Locale locale) {
104        return Bundle.getMessage(locale, "Not_Long");
105    }
106
107    public String getSocketSystemName() {
108        return _socketSystemName;
109    }
110
111    public void setSocketSystemName(String systemName) {
112        _socketSystemName = systemName;
113    }
114
115    /** {@inheritDoc} */
116    @Override
117    public void setup() {
118        try {
119            if ( !_socket.isConnected()
120                    || !_socket.getConnectedSocket().getSystemName()
121                            .equals(_socketSystemName)) {
122                
123                String socketSystemName = _socketSystemName;
124                _socket.disconnect();
125                if (socketSystemName != null) {
126                    MaleSocket maleSocket =
127                            InstanceManager.getDefault(DigitalExpressionManager.class)
128                                    .getBySystemName(socketSystemName);
129                    _socket.disconnect();
130                    if (maleSocket != null) {
131                        _socket.connect(maleSocket);
132                        maleSocket.setup();
133                    } else {
134                        log.error("cannot load digital expression {}", socketSystemName);
135                    }
136                }
137            } else {
138                _socket.getConnectedSocket().setup();
139            }
140        } catch (SocketAlreadyConnectedException ex) {
141            // This shouldn't happen and is a runtime error if it does.
142            throw new RuntimeException("socket is already connected");
143        }
144    }
145
146    /** {@inheritDoc} */
147    @Override
148    public void registerListenersForThisClass() {
149        // Do nothing
150    }
151
152    /** {@inheritDoc} */
153    @Override
154    public void unregisterListenersForThisClass() {
155        // Do nothing
156    }
157    
158    /** {@inheritDoc} */
159    @Override
160    public void disposeMe() {
161    }
162
163    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Not.class);
164
165}