001package jmri.jmrix.roco.z21;
002
003import jmri.jmrix.lenz.XNetReply;
004import jmri.jmrix.lenz.XPressNetMessageFormatter;
005import org.reflections.Reflections;
006import org.slf4j.Logger;
007import org.slf4j.LoggerFactory;
008
009import java.lang.reflect.Constructor;
010import java.lang.reflect.InvocationTargetException;
011import java.util.ArrayList;
012import java.util.List;
013import java.util.Set;
014
015/**
016 * Represents a single response from the XpressNet, with extensions
017 * from Roco for the Z21.
018 *
019 * @author Paul Bender Copyright (C) 2018
020 *
021 */
022public class Z21XNetReply extends XNetReply {
023
024    // Create a new reply.
025    public Z21XNetReply() {
026        super();
027    }
028
029    // Create a new reply from an existing reply
030    public Z21XNetReply(Z21XNetReply reply) {
031        super(reply);
032    }
033
034    /**
035     * Create a reply from an XNetMessage.
036     * @param message message to create reply from.
037     */
038    public Z21XNetReply(Z21XNetMessage message) {
039        super(message);
040    }
041
042    /**
043     * Create a reply from a string of hex characters.
044     * @param message hex character string.
045     */
046    public Z21XNetReply(String message) {
047        super(message);
048    }
049
050    /**
051     * Is this message a service mode response?
052     */
053    @Override
054    public boolean isServiceModeResponse() {
055        return ((getElement(0) == Z21Constants.LAN_X_CV_RESULT_XHEADER && 
056                (getElement(1) == Z21Constants.LAN_X_CV_RESULT_DB0)) ||
057                super.isServiceModeResponse());
058    }
059
060    @Override
061    public boolean isFeedbackMessage() {
062        return (this.getElement(0) == Z21Constants.LAN_X_TURNOUT_INFO ||
063                 super.isFeedbackMessage());
064    }
065
066
067    private static final List<XPressNetMessageFormatter> formatterList = new ArrayList<>();
068    /**
069     * @return a string representation of the reply suitable for display in the
070     * XpressNet monitor.
071     */
072    @Override
073    public String toMonitorString(){
074        if(formatterList.isEmpty()) {
075            try {
076                Reflections reflections = new Reflections("jmri.jmrix");
077                Set<Class<? extends XPressNetMessageFormatter>> f = reflections.getSubTypesOf(XPressNetMessageFormatter.class);
078                for (Class<?> c : f) {
079                    log.debug("Found formatter: {}", f.getClass().getName());
080                    Constructor<?> ctor = c.getConstructor();
081                    formatterList.add((XPressNetMessageFormatter) ctor.newInstance());
082                }
083            } catch (NoSuchMethodException | SecurityException | InstantiationException |
084                     IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
085                log.error("Error instantiating formatter", e);
086            }
087        }
088
089        return formatterList.stream()
090                .filter(f -> f.handlesMessage(this))
091                .findFirst().map(f -> f.formatMessage(this))
092                .orElse(this.toString());
093    }
094
095    private static final Logger log = LoggerFactory.getLogger(Z21XNetReply.class);
096}