001package jmri.jmrit.logixng.expressions;
002
003import java.beans.PropertyChangeEvent;
004import java.beans.PropertyChangeListener;
005import java.beans.PropertyVetoException;
006import java.beans.VetoableChangeListener;
007import java.util.*;
008
009import javax.annotation.Nonnull;
010
011import jmri.*;
012import jmri.jmrit.logixng.*;
013
014/**
015 * Reads a Memory.
016 *
017 * @author Daniel Bergqvist Copyright 2018
018 */
019public class AnalogExpressionMemory extends AbstractAnalogExpression
020        implements PropertyChangeListener, VetoableChangeListener {
021
022    private NamedBeanHandle<Memory> _memoryHandle;
023
024    public AnalogExpressionMemory(String sys, String user)
025            throws BadUserNameException, BadSystemNameException {
026
027        super(sys, user);
028    }
029
030    @Override
031    public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws JmriException {
032        AnalogExpressionManager manager = InstanceManager.getDefault(AnalogExpressionManager.class);
033        String sysName = systemNames.get(getSystemName());
034        String userName = userNames.get(getSystemName());
035        if (sysName == null) sysName = manager.getAutoSystemName();
036        AnalogExpressionMemory copy = new AnalogExpressionMemory(sysName, userName);
037        copy.setComment(getComment());
038        if (_memoryHandle != null) copy.setMemory(_memoryHandle);
039        return manager.registerExpression(copy).deepCopyChildren(this, systemNames, userNames);
040    }
041
042    /** {@inheritDoc} */
043    @Override
044    public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
045        if ("CanDelete".equals(evt.getPropertyName())) { // No I18N
046            if (evt.getOldValue() instanceof Memory) {
047                if (evt.getOldValue().equals(getMemory().getBean())) {
048                    PropertyChangeEvent e = new PropertyChangeEvent(this, "DoNotDelete", null, null);
049                    throw new PropertyVetoException(Bundle.getMessage("Memory_MemoryInUseMemoryExpressionVeto", getDisplayName()), e); // NOI18N
050                }
051            }
052        } else if ("DoDelete".equals(evt.getPropertyName())) { // No I18N
053            if (evt.getOldValue() instanceof Memory) {
054                if (evt.getOldValue().equals(getMemory().getBean())) {
055                    removeMemory();
056                }
057            }
058        }
059    }
060
061    /** {@inheritDoc} */
062    @Override
063    public Category getCategory() {
064        return Category.ITEM;
065    }
066
067    public void setMemory(@Nonnull String memoryName) {
068        assertListenersAreNotRegistered(log, "setMemory");
069        Memory memory = InstanceManager.getDefault(MemoryManager.class).getMemory(memoryName);
070        if (memory != null) {
071            setMemory(memory);
072        } else {
073            removeMemory();
074            log.error("memory \"{}\" is not found", memoryName);
075        }
076    }
077
078    public void setMemory(@Nonnull NamedBeanHandle<Memory> handle) {
079        assertListenersAreNotRegistered(log, "setMemory");
080        _memoryHandle = handle;
081        InstanceManager.memoryManagerInstance().addVetoableChangeListener(this);
082    }
083
084    public void setMemory(@Nonnull Memory memory) {
085        assertListenersAreNotRegistered(log, "setMemory");
086        setMemory(InstanceManager.getDefault(NamedBeanHandleManager.class)
087                .getNamedBeanHandle(memory.getDisplayName(), memory));
088    }
089
090    public void removeMemory() {
091        assertListenersAreNotRegistered(log, "setMemory");
092        if (_memoryHandle != null) {
093            InstanceManager.memoryManagerInstance().removeVetoableChangeListener(this);
094            _memoryHandle = null;
095        }
096    }
097
098    public NamedBeanHandle<Memory> getMemory() {
099        return _memoryHandle;
100    }
101
102    /** {@inheritDoc} */
103    @Override
104    public double evaluate() {
105        if (_memoryHandle != null) {
106            return jmri.util.TypeConversionUtil.convertToDouble(_memoryHandle.getBean().getValue(), false);
107        } else {
108            return 0.0;
109        }
110    }
111
112    /** {@inheritDoc} */
113    @Override
114    public FemaleSocket getChild(int index)
115            throws IllegalArgumentException, UnsupportedOperationException {
116        throw new UnsupportedOperationException("Not supported.");
117    }
118
119    /** {@inheritDoc} */
120    @Override
121    public int getChildCount() {
122        return 0;
123    }
124
125    /** {@inheritDoc} */
126    @Override
127    public String getShortDescription(Locale locale) {
128        return Bundle.getMessage(locale, "AnalogExpressionMemory_Short");
129    }
130
131    /** {@inheritDoc} */
132    @Override
133    public String getLongDescription(Locale locale) {
134        if (_memoryHandle != null) {
135            return Bundle.getMessage(locale, "AnalogExpressionMemory_Long", _memoryHandle.getBean().getDisplayName());
136        } else {
137            return Bundle.getMessage(locale, "AnalogExpressionMemory_Long", "none");
138        }
139    }
140
141    /** {@inheritDoc} */
142    @Override
143    public void setup() {
144        // Do nothing
145    }
146
147    /** {@inheritDoc} */
148    @Override
149    public void registerListenersForThisClass() {
150        if ((! _listenersAreRegistered) && (_memoryHandle != null)) {
151            _memoryHandle.getBean().addPropertyChangeListener("value", this);
152            _listenersAreRegistered = true;
153        }
154    }
155
156    /** {@inheritDoc} */
157    @Override
158    public void unregisterListenersForThisClass() {
159        if (_listenersAreRegistered) {
160            _memoryHandle.getBean().removePropertyChangeListener("value", this);
161            _listenersAreRegistered = false;
162        }
163    }
164
165    /** {@inheritDoc} */
166    @Override
167    public void propertyChange(PropertyChangeEvent evt) {
168        if (getTriggerOnChange()) {
169            getConditionalNG().execute();
170        }
171    }
172
173    /** {@inheritDoc} */
174    @Override
175    public void disposeMe() {
176    }
177
178    /** {@inheritDoc} */
179    @Override
180    public void getUsageDetail(int level, NamedBean bean, List<NamedBeanUsageReport> report, NamedBean cdl) {
181        log.debug("getUsageReport :: AnalogExpressionMemory: bean = {}, report = {}", cdl, report);
182        if (getMemory() != null && bean.equals(getMemory().getBean())) {
183            report.add(new NamedBeanUsageReport("LogixNGExpression", cdl, getLongDescription()));
184        }
185    }
186
187    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AnalogExpressionMemory.class);
188
189}