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.CheckForNull;
010import javax.annotation.Nonnull;
011
012import jmri.*;
013import jmri.jmrit.logixng.*;
014
015/**
016 * Reads a Memory.
017 *
018 * @author Daniel Bergqvist Copyright 2018
019 */
020public class StringExpressionMemory extends AbstractStringExpression
021        implements PropertyChangeListener, VetoableChangeListener {
022
023    private NamedBeanHandle<Memory> _memoryHandle;
024
025    public StringExpressionMemory(String sys, String user)
026            throws BadUserNameException, BadSystemNameException {
027
028        super(sys, user);
029    }
030
031    @Override
032    public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws JmriException {
033        StringExpressionManager manager = InstanceManager.getDefault(StringExpressionManager.class);
034        String sysName = systemNames.get(getSystemName());
035        String userName = userNames.get(getSystemName());
036        if (sysName == null) sysName = manager.getAutoSystemName();
037        StringExpressionMemory copy = new StringExpressionMemory(sysName, userName);
038        copy.setComment(getComment());
039        if (_memoryHandle != null) copy.setMemory(_memoryHandle);
040        return manager.registerExpression(copy).deepCopyChildren(this, systemNames, userNames);
041    }
042
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 String evaluate() {
105        if (_memoryHandle != null) {
106            return jmri.util.TypeConversionUtil.convertToString(_memoryHandle.getBean().getValue(), false);
107        } else {
108            return "";
109        }
110    }
111
112    @Override
113    public FemaleSocket getChild(int index)
114            throws IllegalArgumentException, UnsupportedOperationException {
115        throw new UnsupportedOperationException("Not supported.");
116    }
117
118    @Override
119    public int getChildCount() {
120        return 0;
121    }
122
123    @Override
124    public String getShortDescription(Locale locale) {
125        return Bundle.getMessage(locale, "StringExpressionMemory_Short");
126    }
127
128    @Override
129    public String getLongDescription(Locale locale) {
130        if (_memoryHandle != null) {
131            return Bundle.getMessage(locale, "StringExpressionMemory_Long", _memoryHandle.getBean().getDisplayName());
132        } else {
133            return Bundle.getMessage(locale, "StringExpressionMemory_Long", "none");
134        }
135    }
136
137    /** {@inheritDoc} */
138    @Override
139    public void setup() {
140        // Do nothing
141    }
142
143    /** {@inheritDoc} */
144    @Override
145    public void registerListenersForThisClass() {
146        if ((! _listenersAreRegistered) && (_memoryHandle != null)) {
147            _memoryHandle.getBean().addPropertyChangeListener("value", this);
148            _listenersAreRegistered = true;
149        }
150    }
151
152    /** {@inheritDoc} */
153    @Override
154    public void unregisterListenersForThisClass() {
155        if (_listenersAreRegistered) {
156            _memoryHandle.getBean().removePropertyChangeListener("value", this);
157            _listenersAreRegistered = false;
158        }
159    }
160
161    /** {@inheritDoc} */
162    @Override
163    public void propertyChange(PropertyChangeEvent evt) {
164        if (getTriggerOnChange()) {
165            getConditionalNG().execute();
166        }
167    }
168
169    /** {@inheritDoc} */
170    @Override
171    public void disposeMe() {
172    }
173
174    /** {@inheritDoc} */
175    @Override
176    public void getUsageDetail(int level, NamedBean bean, List<NamedBeanUsageReport> report, NamedBean cdl) {
177        log.debug("getUsageReport :: StringExpressionMemory: bean = {}, report = {}", cdl, report);
178        if (getMemory() != null && bean.equals(getMemory().getBean())) {
179            report.add(new NamedBeanUsageReport("LogixNGExpression", cdl, getLongDescription()));
180        }
181    }
182
183    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(StringExpressionMemory.class);
184
185}