001package jmri.util;
002
003import java.util.Objects;
004
005import javax.annotation.Nonnull;
006
007import jmri.ExpectedState;
008import jmri.InstanceManager;
009import jmri.NamedBean;
010import jmri.NamedBeanHandle;
011import jmri.NamedBeanHandleManager;
012import jmri.beans.Bean;
013
014/**
015 * Retain a NamedBean and its expected value (called a state in this class).
016 * <p>
017 * Note the NamedBean is held in a {@link NamedBeanHandle}.
018 *
019 * @author Randall Wood Copyright 2017
020 * @param <T> the supported type of NamedBean
021 * @param <S> the supported type of value
022 */
023public class NamedBeanExpectedValue<T extends NamedBean, S extends Object> extends Bean implements ExpectedState<T, S> {
024
025    private final NamedBeanHandle<T> handle;
026    private S state;
027
028    /**
029     * Create a NamedBeanExpectedValue, using the provided tracked name for the
030     * NamedBean.
031     *
032     * @param bean  the bean
033     * @param name  the name
034     * @param state the expected state
035     */
036    public NamedBeanExpectedValue(@Nonnull T bean, @Nonnull String name, @Nonnull S state) {
037        this.handle = InstanceManager.getDefault(NamedBeanHandleManager.class).getNamedBeanHandle(name, bean);
038        this.state = state;
039    }
040
041    /**
042     * Create a NamedBeanExpectedValue, using {@link NamedBean#getDisplayName()}
043     * to provide the tracked name for the NamedBean.
044     *
045     * @param bean  the bean
046     * @param state the expected state
047     */
048    public NamedBeanExpectedValue(@Nonnull T bean, S state) {
049        this(bean, bean.getDisplayName(), state);
050    }
051
052    @Override
053    public S getExpectedState() {
054        return state;
055    }
056
057    @Override
058    public void setExpectedState(@Nonnull S state) throws UnsupportedOperationException {
059        Objects.requireNonNull(state, "state Integer must not be null");
060        S old = this.state;
061        this.state = state;
062        this.propertyChangeSupport.firePropertyChange(EXPECTED_STATE, old, state);
063    }
064
065    @Nonnull
066    @Override
067    public T getObject() {
068        return this.handle.getBean();
069    }
070
071    /**
072     * Get the name of the contained NamedBean object.
073     *
074     * @return the name
075     */
076    @Nonnull
077    public String getName() {
078        return this.handle.getName();
079    }
080}