001package jmri.jmrit.logixng.implementation;
002
003import java.beans.PropertyChangeEvent;
004import java.beans.PropertyChangeListener;
005import java.beans.PropertyVetoException;
006import java.util.*;
007
008import javax.annotation.Nonnull;
009
010import jmri.*;
011import jmri.jmrit.logixng.*;
012
013/**
014 * Every AnalogExpressionBean has an DefaultMaleAnalogExpressionSocket as its parent.
015 * 
016 * @author Daniel Bergqvist Copyright 2018
017 */
018public class DefaultMaleAnalogExpressionSocket extends AbstractMaleSocket implements MaleAnalogExpressionSocket {
019
020//    private final AnalogExpressionBean ((AnalogExpressionBean)getObject());
021    private DebugConfig _debugConfig = null;
022    private boolean _enabled = true;
023
024
025    public DefaultMaleAnalogExpressionSocket(@Nonnull BaseManager<? extends NamedBean> manager, @Nonnull AnalogExpressionBean expression) {
026        super(manager, expression);
027    }
028
029    /** {@inheritDoc} */
030    @Override
031    public boolean getTriggerOnChange() {
032        return ((AnalogExpressionBean)getObject()).getTriggerOnChange();
033    }
034    
035    /** {@inheritDoc} */
036    @Override
037    public void setTriggerOnChange(boolean triggerOnChange) {
038        ((AnalogExpressionBean)getObject()).setTriggerOnChange(triggerOnChange);
039    }
040    
041    /**
042     * Get the value of the AnalogExpressionBean.
043     */
044    private double internalEvaluate() throws JmriException {
045        double result = ((AnalogExpressionBean)getObject()).evaluate();
046        
047        if (Double.isNaN(result)) {
048            throw new IllegalArgumentException("The result is NaN");
049        }
050        if (result == Double.NEGATIVE_INFINITY) {
051            throw new IllegalArgumentException("The result is negative infinity");
052        }
053        if (result == Double.POSITIVE_INFINITY) {
054            throw new IllegalArgumentException("The result is positive infinity");
055        }
056        return result;
057    }
058
059    /** {@inheritDoc} */
060    @Override
061    public double evaluate() throws JmriException {
062        if (! _enabled) {
063            return 0.0;
064        }
065        
066        if ((_debugConfig != null)
067                && ((AnalogExpressionDebugConfig)_debugConfig)._forceResult) {
068            return ((AnalogExpressionDebugConfig)_debugConfig)._result;
069        }
070        
071        ConditionalNG conditionalNG = getConditionalNG();
072        
073        int currentStackPos = conditionalNG.getStack().getCount();
074        
075        double result = 0.0;
076        try {
077            conditionalNG.getSymbolTable().createSymbols(_localVariables);
078            result = internalEvaluate();
079        } catch (JmriException e) {
080            if (e.getErrors() != null) {
081                handleError(this, Bundle.getMessage("ExceptionEvaluateMulti"), e.getErrors(), e, log);
082            } else {
083                handleError(this, Bundle.getMessage("ExceptionEvaluate", e.getLocalizedMessage()), e, log);
084            }
085        } catch (RuntimeException e) {
086            handleError(this, Bundle.getMessage("ExceptionEvaluate", e.getLocalizedMessage()), e, log);
087        }
088        
089        conditionalNG.getStack().setCount(currentStackPos);
090        conditionalNG.getSymbolTable().removeSymbols(_localVariables);
091        
092        return result;
093    }
094    
095    @Override
096    public int getState() {
097        return ((AnalogExpressionBean)getObject()).getState();
098    }
099
100    @Override
101    public String getDisplayName() {
102        return ((AnalogExpressionBean)getObject()).getDisplayName();
103    }
104
105    @Override
106    public void disposeMe() {
107        ((AnalogExpressionBean)getObject()).dispose();
108    }
109
110    /**
111     * Register listeners if this object needs that.
112     */
113    @Override
114    public void registerListenersForThisClass() {
115        ((AnalogExpressionBean)getObject()).registerListeners();
116    }
117    
118    /**
119     * Register listeners if this object needs that.
120     */
121    @Override
122    public void unregisterListenersForThisClass() {
123        ((AnalogExpressionBean)getObject()).unregisterListeners();
124    }
125    
126    @Override
127    public void setState(int s) throws JmriException {
128        ((AnalogExpressionBean)getObject()).setState(s);
129    }
130
131    @Override
132    public String describeState(int state) {
133        return Bundle.getMessage("BeanStateUnknown");
134    }
135
136    @Override
137    public String getComment() {
138        return ((AnalogExpressionBean)getObject()).getComment();
139    }
140
141    @Override
142    public void setComment(String comment) {
143        ((AnalogExpressionBean)getObject()).setComment(comment);
144    }
145
146    @Override
147    public void setProperty(String key, Object value) {
148        ((AnalogExpressionBean)getObject()).setProperty(key, value);
149    }
150
151    @Override
152    public Object getProperty(String key) {
153        return ((AnalogExpressionBean)getObject()).getProperty(key);
154    }
155
156    @Override
157    public void removeProperty(String key) {
158        ((AnalogExpressionBean)getObject()).removeProperty(key);
159    }
160
161    @Override
162    public Set<String> getPropertyKeys() {
163        return ((AnalogExpressionBean)getObject()).getPropertyKeys();
164    }
165
166    @Override
167    public String getBeanType() {
168        return ((AnalogExpressionBean)getObject()).getBeanType();
169    }
170
171    @Override
172    public int compareSystemNameSuffix(String suffix1, String suffix2, NamedBean n2) {
173        return ((AnalogExpressionBean)getObject()).compareSystemNameSuffix(suffix1, suffix2, n2);
174    }
175
176    /** {@inheritDoc} */
177    @Override
178    public void setDebugConfig(DebugConfig config) {
179        _debugConfig = config;
180    }
181
182    /** {@inheritDoc} */
183    @Override
184    public DebugConfig getDebugConfig() {
185        return _debugConfig;
186    }
187
188    /** {@inheritDoc} */
189    @Override
190    public DebugConfig createDebugConfig() {
191        return new AnalogExpressionDebugConfig();
192    }
193
194    /** {@inheritDoc} */
195    @Override
196    public void setEnabled(boolean enable) {
197        _enabled = enable;
198        if (isActive()) {
199            registerListeners();
200        } else {
201            unregisterListeners();
202        }
203    }
204    
205    /** {@inheritDoc} */
206    @Override
207    public void setEnabledFlag(boolean enable) {
208        _enabled = enable;
209    }
210    
211    /** {@inheritDoc} */
212    @Override
213    public boolean isEnabled() {
214        return _enabled;
215    }
216
217
218
219    public static class AnalogExpressionDebugConfig implements MaleSocket.DebugConfig {
220        
221        // If true, the socket is returning the value of "result" instead of
222        // executing the expression.
223        public boolean _forceResult = false;
224        
225        // The result if the result is forced.
226        public double _result = 0.0f;
227        
228        @Override
229        public DebugConfig getCopy() {
230            AnalogExpressionDebugConfig config = new AnalogExpressionDebugConfig();
231            config._forceResult = _forceResult;
232            config._result = _result;
233            return config;
234        }
235        
236    }
237    
238    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultMaleAnalogExpressionSocket.class);
239
240}