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