001package jmri.jmrix.rps; 002 003import java.util.Comparator; 004import java.util.Locale; 005import java.util.ResourceBundle; 006import javax.annotation.Nonnull; 007 008import jmri.*; 009import jmri.jmrix.ConfiguringSystemConnectionMemo; 010import jmri.jmrix.DefaultSystemConnectionMemo; 011import jmri.util.NamedBeanComparator; 012import jmri.Manager.NameValidity; 013import org.slf4j.Logger; 014import org.slf4j.LoggerFactory; 015 016/** 017 * Minimal implementation of SystemConnectionMemo. 018 * 019 * @author Randall Wood randall.h.wood@alexandriasoftware.com 020 */ 021public class RpsSystemConnectionMemo extends DefaultSystemConnectionMemo implements ConfiguringSystemConnectionMemo { 022 023 public RpsSystemConnectionMemo(@Nonnull String prefix, @Nonnull String name) { 024 super(prefix, name); 025 InstanceManager.store(this, RpsSystemConnectionMemo.class); // also register as specific type 026 027 // create and register the ComponentFactory 028 InstanceManager.store(new jmri.jmrix.rps.swing.RpsComponentFactory(this), 029 jmri.jmrix.swing.ComponentFactory.class); 030 031 log.debug("Created RpsSystemConnectionMemo with prefix {}", prefix); 032 } 033 034 public RpsSystemConnectionMemo() { 035 this("R", "RPS"); // default connection prefix, default RPS product name NOI18N 036 log.debug("Created nameless RpsSystemConnectionMemo"); 037 } 038 039 @Override 040 protected ResourceBundle getActionModelResourceBundle() { 041 return null; 042 } 043 044 @Override 045 public <B extends NamedBean> Comparator<B> getNamedBeanComparator(Class<B> type) { 046 return new NamedBeanComparator<>(); 047 } 048 049 @Override 050 public void configureManagers() { 051 InstanceManager.setSensorManager(getSensorManager()); 052 InstanceManager.setReporterManager(getReporterManager()); 053 register(); 054 } 055 056 /** 057 * @return The RpsSensorManager associated with this connection. 058 */ 059 public RpsSensorManager getSensorManager() { 060 if (getDisabled()) { 061 return null; 062 } 063 return (RpsSensorManager) classObjectMap.computeIfAbsent(SensorManager.class, (Class<?> c) -> { return new RpsSensorManager(this); }); 064 } 065 066 /** 067 * @return The RpsReporterManager associated with this connection 068 */ 069 public RpsReporterManager getReporterManager() { 070 if (getDisabled()) { 071 return null; 072 } 073 return (RpsReporterManager) classObjectMap.computeIfAbsent(ReporterManager.class, (Class<?> c) -> { return new RpsReporterManager(this); }); 074 } 075 076 /** 077 * Validate RPS system name format. 078 * 079 * @param name the name to validate 080 * @param manager the manager requesting the validation 081 * @param locale the locale for user messages 082 * @return name, unchanged 083 */ 084 public String validateSystemNameFormat(String name, Manager<?> manager, Locale locale) { 085 manager.validateSystemNamePrefix(name, locale); 086 String[] points = name.substring(manager.getSystemNamePrefix().length()).split(";"); 087 if (points.length < 3) { 088 throw new NamedBean.BadSystemNameException( 089 Bundle.getMessage(Locale.ENGLISH, "SystemNameInvalidMissingPoints", name, points.length), 090 Bundle.getMessage(locale, "SystemNameInvalidMissingPoints", name, points.length)); 091 } 092 for (int i = 0; i < points.length; i++) { 093 if (!points[i].startsWith("(") || !points[i].endsWith(")")) { 094 throw new NamedBean.BadSystemNameException( 095 Bundle.getMessage(Locale.ENGLISH, "SystemNameInvalidPointInvalid", name, points[i]), 096 Bundle.getMessage(locale, "SystemNameInvalidPointInvalid", name, points[i])); 097 } 098 String[] coords = points[i].substring(1, points[i].length() - 1).split(","); 099 if (coords.length != 3) { 100 throw new NamedBean.BadSystemNameException( 101 Bundle.getMessage(Locale.ENGLISH, "SystemNameInvalidPointInvalid", name, points[i]), 102 Bundle.getMessage(locale, "SystemNameInvalidPointInvalid", name, points[i])); 103 } 104 for (int j = 0; j < 3; j++) { 105 try { 106 Double.valueOf(coords[j]); 107 } catch (NumberFormatException ex) { 108 throw new NamedBean.BadSystemNameException( 109 Bundle.getMessage(Locale.ENGLISH, "SystemNameInvalidCoordInvalid", name, points[i], coords[j]), 110 Bundle.getMessage(locale, "SystemNameInvalidCoordInvalid", name, points[i], coords[j])); 111 } 112 } 113 } 114 return name; 115 } 116 117 /** 118 * Validate RPS system name format. 119 * 120 * @param systemName system name. 121 * @param type e.g. S for Sensor, T for Turnout. 122 * @return VALID if system name has a valid format, else return INVALID 123 */ 124 public NameValidity validSystemNameFormat(@Nonnull String systemName, char type) { 125 // validate the system Name leader characters 126 if (!(systemName.startsWith(getSystemPrefix() + type))) { 127 // here if an illegal format 128 log.error("invalid character in header field of system name: {}", systemName); 129 return NameValidity.INVALID; 130 } 131 String s = systemName.substring(getSystemPrefix().length() + 1); 132 String[] pStrings = s.split(";"); 133 if (pStrings.length < 3) { 134 log.warn("need to have at least 3 points in {}", systemName); 135 return NameValidity.INVALID; 136 } 137 for (int i = 0; i < pStrings.length; i++) { 138 if (!(pStrings[i].startsWith("(")) || !(pStrings[i].endsWith(")"))) { 139 // here if an illegal format 140 log.warn("missing brackets in point {}: \"{}\"", i, pStrings[i]); 141 return NameValidity.INVALID; 142 } 143 // remove leading ( and trailing ) 144 String coords = pStrings[i].substring(1, pStrings[i].length() - 1); 145 try { 146 String[] coord = coords.split(","); 147 if (coord.length != 3) { 148 log.warn("need to have three coordinates in point {}: \"{}\"", i, pStrings[i]); 149 return NameValidity.INVALID; 150 } 151 double x = Double.valueOf(coord[0]); 152 double y = Double.valueOf(coord[1]); 153 double z = Double.valueOf(coord[2]); 154 log.debug("succes converting systemName point {} to {},{},{}", i, x, y, z); 155 // valid, continue 156 } catch (NumberFormatException e) { 157 return NameValidity.INVALID; 158 } 159 } 160 return NameValidity.VALID; 161 } 162 163 private final static Logger log = LoggerFactory.getLogger(RpsSystemConnectionMemo.class); 164 165}