001package jmri.jmrit.logixng.expressions;
002
003import java.beans.*;
004import java.util.*;
005
006import javax.annotation.Nonnull;
007
008import jmri.*;
009import jmri.jmrit.logixng.*;
010
011/**
012 * Returns the last result of a digital expression.
013 * 
014 * @author Daniel Bergqvist Copyright 2021
015 */
016public class LastResultOfDigitalExpression extends AbstractDigitalExpression
017        implements PropertyChangeListener, VetoableChangeListener {
018
019    private NamedBeanHandle<DigitalExpressionBean> _digitalExpressionHandle;
020    
021    public LastResultOfDigitalExpression(String sys, String user)
022            throws BadUserNameException, BadSystemNameException {
023        super(sys, user);
024    }
025    
026    @Override
027    public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) {
028        DigitalExpressionManager manager = InstanceManager.getDefault(DigitalExpressionManager.class);
029        String sysName = systemNames.get(getSystemName());
030        String userName = userNames.get(getSystemName());
031        if (sysName == null) sysName = manager.getAutoSystemName();
032        LastResultOfDigitalExpression copy = new LastResultOfDigitalExpression(sysName, userName);
033        copy.setComment(getComment());
034        if (_digitalExpressionHandle != null) copy.setDigitalExpression(_digitalExpressionHandle);
035        return manager.registerExpression(copy);
036    }
037    
038    public void setDigitalExpression(@Nonnull String digitalExpressionName) {
039        assertListenersAreNotRegistered(log, "setDigitalExpression");
040        DigitalExpressionBean digitalExpression =
041                InstanceManager.getDefault(DigitalExpressionManager.class)
042                        .getNamedBean(digitalExpressionName);
043        if (digitalExpression != null) {
044            // We need the male socket, not the expression itself
045            if (!(digitalExpression instanceof MaleSocket)) {
046                digitalExpression = (DigitalExpressionBean)digitalExpression.getParent();
047            }
048            setDigitalExpression(digitalExpression);
049        } else {
050            removeDigitalExpression();
051            log.error("digitalExpression \"{}\" is not found", digitalExpressionName);
052        }
053    }
054    
055    public void setDigitalExpression(@Nonnull NamedBeanHandle<DigitalExpressionBean> handle) {
056        assertListenersAreNotRegistered(log, "setDigitalExpression");
057        _digitalExpressionHandle = handle;
058        InstanceManager.getDefault(DigitalExpressionManager.class).addVetoableChangeListener(this);
059    }
060    
061    public void setDigitalExpression(@Nonnull DigitalExpressionBean digitalExpression) {
062        assertListenersAreNotRegistered(log, "setDigitalExpression");
063        setDigitalExpression(InstanceManager.getDefault(NamedBeanHandleManager.class)
064                .getNamedBeanHandle(digitalExpression.getDisplayName(), digitalExpression));
065    }
066    
067    public void removeDigitalExpression() {
068        assertListenersAreNotRegistered(log, "setDigitalExpression");
069        if (_digitalExpressionHandle != null) {
070            InstanceManager.getDefault(DigitalExpressionManager.class).removeVetoableChangeListener(this);
071            _digitalExpressionHandle = null;
072        }
073    }
074    
075    public NamedBeanHandle<DigitalExpressionBean> getDigitalExpression() {
076        return _digitalExpressionHandle;
077    }
078    
079    @Override
080    public void vetoableChange(java.beans.PropertyChangeEvent evt) throws java.beans.PropertyVetoException {
081        if ("CanDelete".equals(evt.getPropertyName())) { // No I18N
082            if (evt.getOldValue() instanceof DigitalExpression) {
083                if (evt.getOldValue().equals(getDigitalExpression().getBean())) {
084                    PropertyChangeEvent e = new PropertyChangeEvent(this, "DoNotDelete", null, null);
085                    throw new PropertyVetoException(Bundle.getMessage("LastResultOfDigitalExpression_BeanInUseVeto", getDisplayName()), e); // NOI18N
086                }
087            }
088        } else if ("DoDelete".equals(evt.getPropertyName())) { // No I18N
089            if (evt.getOldValue() instanceof DigitalExpression) {
090                if (evt.getOldValue().equals(getDigitalExpression().getBean())) {
091                    removeDigitalExpression();
092                }
093            }
094        }
095    }
096    
097    /** {@inheritDoc} */
098    @Override
099    public Category getCategory() {
100        return Category.OTHER;
101    }
102    
103    /** {@inheritDoc} */
104    @Override
105    public boolean evaluate() {
106        if (_digitalExpressionHandle != null) {
107            MaleSocket m = (MaleSocket) _digitalExpressionHandle.getBean();
108            while ((m != null) && (! (m instanceof MaleDigitalExpressionSocket))) {
109                m = (MaleSocket) m.getObject();
110            }
111            if (m == null) {
112                throw new RuntimeException("The digital expression "
113                        + _digitalExpressionHandle.getName()
114                        + " is not contained in a DigitalExpressionSocket");
115            }
116            return ((MaleDigitalExpressionSocket)m).getLastResult();
117        }
118        return false;
119    }
120    
121    @Override
122    public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException {
123        throw new UnsupportedOperationException("Not supported.");
124    }
125    
126    @Override
127    public int getChildCount() {
128        return 0;
129    }
130    
131    @Override
132    public String getShortDescription(Locale locale) {
133        return Bundle.getMessage(locale, "LastResultOfDigitalExpression_Short");
134    }
135    
136    @Override
137    public String getLongDescription(Locale locale) {
138        String beanName;
139        if (_digitalExpressionHandle != null) {
140            beanName = _digitalExpressionHandle.getBean().getDisplayName();
141        } else {
142            beanName = Bundle.getMessage(locale, "BeanNotSelected");
143        }
144        return Bundle.getMessage(locale, "LastResultOfDigitalExpression_Long",
145                beanName);
146    }
147
148    /** {@inheritDoc} */
149    @Override
150    public void setup() {
151        // Do nothing
152    }
153    
154    /** {@inheritDoc} */
155    @Override
156    public void registerListenersForThisClass() {
157        if (!_listenersAreRegistered && (_digitalExpressionHandle != null)) {
158            _digitalExpressionHandle.getBean()
159                    .addPropertyChangeListener(PROPERTY_LAST_RESULT_CHANGED, this);
160            _listenersAreRegistered = true;
161        }
162    }
163    
164    /** {@inheritDoc} */
165    @Override
166    public void unregisterListenersForThisClass() {
167        if (_listenersAreRegistered) {
168            _digitalExpressionHandle.getBean()
169                    .removePropertyChangeListener(PROPERTY_LAST_RESULT_CHANGED, this);
170            _listenersAreRegistered = false;
171        }
172    }
173    
174    /** {@inheritDoc} */
175    @Override
176    public void propertyChange(PropertyChangeEvent evt) {
177        getConditionalNG().execute();
178    }
179    
180    /** {@inheritDoc} */
181    @Override
182    public void disposeMe() {
183    }
184    
185    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LastResultOfDigitalExpression.class);
186
187}