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}