001package jmri.jmrix.maple;
002
003import java.util.Locale;
004import javax.annotation.Nonnull;
005import jmri.Turnout;
006import jmri.managers.AbstractTurnoutManager;
007
008/**
009 * Implement turnout manager for serial systems
010 * <p>
011 * System names are "KTnnn", where K is the user configurable system prefix,
012 * nnn is the turnout number without padding.
013 *
014 * @author Bob Jacobsen Copyright (C) 2003, 2008
015 */
016public class SerialTurnoutManager extends AbstractTurnoutManager {
017
018    public SerialTurnoutManager(MapleSystemConnectionMemo memo) {
019        super(memo);
020    }
021
022    /**
023     * {@inheritDoc}
024     */
025    @Override
026    @Nonnull
027    public MapleSystemConnectionMemo getMemo() {
028        return (MapleSystemConnectionMemo) memo;
029    }
030
031    /**
032     * {@inheritDoc}
033     */
034    @Nonnull
035    @Override
036    protected Turnout createNewTurnout(@Nonnull String systemName, String userName) throws IllegalArgumentException {
037        // validate the system name, and normalize it
038        String sName = SerialAddress.normalizeSystemName(systemName, getSystemPrefix());
039        if (sName.isEmpty()) {
040            // system name is not valid
041            throw new IllegalArgumentException("Cannot create System Name from " + systemName);
042        }
043        // does this turnout already exist
044        Turnout t = getBySystemName(sName);
045        if (t != null) {
046            return t;
047        }
048
049        // check if the addressed output bit is available
050        int bitNum = SerialAddress.getBitFromSystemName(sName, getSystemPrefix());
051        if (bitNum == 0) {
052            throw new IllegalArgumentException("Cannot get Bit from System Name " + systemName + " " + sName);
053        }
054        String conflict = SerialAddress.isOutputBitFree(bitNum, getSystemPrefix());
055        if ((!conflict.isEmpty()) && (!conflict.equals(sName))) {
056            log.error("{} assignment conflict with {}.", sName, conflict);
057            throw new IllegalArgumentException("The output bit " + bitNum + ", is currently assigned to " + conflict + ".");
058        }
059
060        // create the turnout
061        t = new SerialTurnout(sName, userName, getMemo());
062
063        // does system name correspond to configured hardware
064        if (!SerialAddress.validSystemNameConfig(sName, 'T', getMemo())) {
065            // system name does not correspond to configured hardware
066            log.warn("Turnout '{}' refers to an unconfigured output bit.", sName);
067            jmri.util.swing.JmriJOptionPane.showMessageDialog(null, "WARNING - The Turnout just added, "
068                    + sName + ", refers to an unconfigured output bit.", "Configuration Warning",
069                    jmri.util.swing.JmriJOptionPane.INFORMATION_MESSAGE);
070        }
071        return t;
072    }
073
074    @Override
075    public boolean allowMultipleAdditions(@Nonnull String systemName) {
076        return true;
077    }
078
079    /**
080     * {@inheritDoc}
081     */
082    @Override
083    @Nonnull
084    public String validateSystemNameFormat(@Nonnull String name, @Nonnull Locale locale) {
085        return SerialAddress.validateSystemNameFormat(name, this, locale);
086    }
087
088    /**
089     * {@inheritDoc}
090     */
091    @Override
092    public NameValidity validSystemNameFormat(@Nonnull String systemName) {
093        return (SerialAddress.validSystemNameFormat(systemName, typeLetter(), getSystemPrefix()));
094    }
095
096    /**
097     * {@inheritDoc}
098     */
099    @Override
100    public String getEntryToolTip() {
101        return Bundle.getMessage("AddOutputEntryToolTip");
102    }
103
104    /**
105     * Get from the user, the number of addressed bits used to control a
106     * turnout. Normally this is 1, and the default routine returns 1
107     * automatically. Turnout Managers for systems that can handle multiple
108     * control bits should override this method with one which asks the user to
109     * specify the number of control bits. If the user specifies more than one
110     * control bit, this method should check if the additional bits are
111     * available (not assigned to another object). If the bits are not
112     * available, this method should return 0 for number of control bits, after
113     * informing the user of the problem. This function is called whenever a new
114     * turnout is defined in the Turnout table. It can also be used to set up
115     * other turnout control options, such as pulsed control of turnout
116     * machines.
117     */
118// Code below to do with having a pulsed turnout type is commented out for current Maple version
119// /**
120//  * Get from the user, the type of output to be used bits to control a turnout.
121//  * Normally this is 0 for 'steady state' control, and the default routine
122//  * returns 0 automatically.
123//  * Turnout Managers for systems that can handle pulsed control as well as
124//  * steady state control should override this method with one which asks
125//  * the user to specify the type of control to be used.  The routine should
126//  * return 0 for 'steady state' control, or n for 'pulsed' control, where n
127//  * specifies the duration of the pulse (normally in seconds).
128// */
129//  public int askControlType(String systemName) {
130//  // ask if user wants 'steady state' output (stall motors, e.g., Tortoises) or
131//  //   'pulsed' output (some turnout controllers).
132//  int iType = selectOutputType();
133//  if (iType == javax.swing.JOptionPane.CLOSED_OPTION) {
134//   /* user cancelled without selecting an output type */
135//   iType = 0;
136//   log.warn("User cancelled without selecting output type. Defaulting to 'steady state'.");
137//  }
138//  // Note: If the user selects 'pulsed', this routine defaults to 1 second.
139//  return (iType);
140// }
141//    /**
142//     * Public method to allow user to specify one or two output bits for turnout control
143//  *  Note: This method returns 1 or 2 if the user selected, or 0 if the user cancelled
144//  *         without selecting.
145//  */
146// public int selectNumberOfControlBits() {
147//  int iNum = 0;
148//  iNum = javax.swing.JOptionPane.showOptionDialog(null,
149//    "How many output bits should be used to control this turnout?",
150//     "Turnout Question",javax.swing.JOptionPane.DEFAULT_OPTION,
151//      javax.swing.JOptionPane.QUESTION_MESSAGE,
152//      null, new String[] {"Use 1 bit", "Use 2 bits"}, "Use 1 bit");
153//  return iNum;
154// }
155//    /**
156//     * Public method to allow user to specify pulsed or steady state for two output bits
157//  * for turnout control
158//  *  Note: This method returns 1 for steady state or 2 for pulsed if the user selected,
159//  *   or 0 if the user cancelled without selecting.
160//  */
161// public int selectOutputType() {
162//  int iType = 0;
163//  iType = javax.swing.JOptionPane.showOptionDialog(null,
164//    "Should the output bit(s) be 'steady state' or 'pulsed'?",
165//     "Output Bits Question",javax.swing.JOptionPane.DEFAULT_OPTION,
166//      javax.swing.JOptionPane.QUESTION_MESSAGE,
167//      null, new String[] {"Steady State Output", "Pulsed Output"}, "Steady State Output");
168//  return iType;
169// }
170//    /**
171//     * Public method to notify user when the second bit of a proposed two output bit turnout
172//  *  has a conflict with another assigned bit
173//     */
174// public void notifySecondBitConflict(String conflict,int bitNum) {
175//  javax.swing.JOptionPane.showMessageDialog(null,"The second output bit, "+bitNum+
176//   ", is currently assigned to "+conflict+". Turnout cannot be created as "+
177//     "you specified.", "Assignment Conflict",
178//       javax.swing.JOptionPane.INFORMATION_MESSAGE,null);
179// }
180
181
182    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SerialTurnoutManager.class);
183
184}