001/* ProgrammingMode.java */
002package jmri;
003
004import javax.annotation.Nonnull;
005
006/**
007 * Denote a single programming mode.
008 * <p>
009 * User code gets a list of available modes from the {@link Programmer} or
010 * {@link AddressedProgrammer} in use. It then selects a mode to use and
011 * indicates it via a setMode() call.
012 * <p>
013 * A ProgrammingMode has a user-readable name to help humans select it.
014 * <p>
015 * We define a number of modes as constants because they are common across so
016 * many DCC-specific implementations, they've become defacto standards.
017 * <p>
018 * More specific definitions (and Bundle entries) should retreat to specific
019 * Programmer implementations. The whole idea is to have code deal with the
020 * modes that a specific {@link Programmer} provides, not make assumptions about
021 * global values.
022 *
023 * @see jmri.Programmer
024 * @author Bob Jacobsen Copyright (C) 2014
025 */
026@javax.annotation.concurrent.Immutable
027public final class ProgrammingMode {
028
029    /**
030     * NMRA "Paged" mode
031     */
032    public static final ProgrammingMode PAGEMODE = new ProgrammingMode("PAGEMODE");
033
034    /**
035     * NMRA "Operations" or "Programming on the main" mode, using only the
036     * bit-wise operations
037     */
038    public static final ProgrammingMode OPSBITMODE = new ProgrammingMode("OPSBITMODE");
039
040    /**
041     * NMRA "Programming on the main" mode for stationary decoders, using only
042     * the byte-wise operations and "extended" addressing.
043     */
044    public static final ProgrammingMode OPSACCEXTBYTEMODE = new ProgrammingMode("OPSACCEXTBYTEMODE");
045
046    /**
047     * NMRA "Programming on the main" mode for stationary decoders, using only
048     * the bit-wise operations. Note that this is defined as using the "normal",
049     * not "extended" addressing.
050     */
051    public static final ProgrammingMode OPSACCBITMODE = new ProgrammingMode("OPSACCBITMODE");
052
053    /**
054     * NMRA "Programming on the main" mode for stationary decoders, using only
055     * the bit-wise operations and "extended" addressing.
056     */
057    public static final ProgrammingMode OPSACCEXTBITMODE = new ProgrammingMode("OPSACCEXTBITMODE");
058
059    /**
060     * NMRA "Programming on the main" mode for stationary decoders, using only
061     * the byte-wise operations. Note that this is defined as using the
062     * "normal", not "extended" addressing.
063     */
064    public static final ProgrammingMode OPSACCBYTEMODE = new ProgrammingMode("OPSACCBYTEMODE");
065
066    /**
067     * NMRA "Address-only" mode. Often implemented as a proper subset of
068     * "Register" mode, as the underlying operation is the same.
069     */
070    public static final ProgrammingMode ADDRESSMODE = new ProgrammingMode("ADDRESSMODE");
071
072    /**
073     * NMRA "Operations" or "Programming on the main" mode, using only the
074     * byte-wise operations.
075     */
076    public static final ProgrammingMode OPSBYTEMODE = new ProgrammingMode("OPSBYTEMODE");
077
078    /**
079     * NMRA "Direct" mode, using only the byte-wise operations.
080     */
081    public static final ProgrammingMode DIRECTBYTEMODE = new ProgrammingMode("DIRECTBYTEMODE");
082
083    /**
084     * NMRA "Register" mode.
085     */
086    public static final ProgrammingMode REGISTERMODE = new ProgrammingMode("REGISTERMODE");
087
088    /**
089     * NMRA "Direct" mode, using only the bit-wise operations.
090     */
091    public static final ProgrammingMode DIRECTBITMODE = new ProgrammingMode("DIRECTBITMODE");
092
093    /**
094     * NMRA "Direct" mode, using both the bit-wise and byte-wise operations.
095     */
096    public static final ProgrammingMode DIRECTMODE = new ProgrammingMode("DIRECTMODE");
097
098    /**
099     * Create a ProgrammingMode instance.
100     *
101     * @param standardName a name, not to be translated, for internal use
102     */
103    public ProgrammingMode(@Nonnull String standardName) {
104        this.standardName = standardName;
105        this.localName = Bundle.getMessage(standardName);  // note in jmri package
106    }
107
108    /**
109     * Create an instance with a provided localized name.
110     * <p>
111     * This is useful when creating a ProgrammingMode deep within some
112     * system-specific code, and translations cannot be added to the top-level
113     * jmri.Bundle.
114     *
115     * @param standardName a name, not to be translated, for internal use
116     * @param localName    a localized, human-readable name for the mode
117     */
118    public ProgrammingMode(@Nonnull String standardName, @Nonnull String localName) {
119        this.standardName = standardName;
120        this.localName = localName;
121    }
122
123    /**
124     * Display the localized (human readable) name.
125     *
126     * @return the localized name
127     */
128    @Override
129    @Nonnull
130    public String toString() {
131        return localName;
132    }
133
134    /**
135     * Return the standard (not localized, human readable) name.
136     *
137     * @return the standard name
138     */
139    @Nonnull
140    public String getStandardName() {
141        return standardName;
142    }
143
144    @Override
145    public boolean equals(Object o) {
146        if (this == o) {
147            return true;
148        }
149        if (!(o instanceof ProgrammingMode)) {
150            return false;
151        }
152        ProgrammingMode that = (ProgrammingMode) o;
153        return this.standardName.equals(that.standardName);
154    }
155
156    @Override
157    public int hashCode() {
158        return standardName.hashCode();
159    }
160
161    @Nonnull
162    private final String standardName;
163    @Nonnull
164    private final String localName;
165
166}