001package jmri.jmrix.lenz.swing.mon;
002
003import jmri.jmrix.Message;
004import jmri.jmrix.lenz.*;
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 * Panel displaying (and logging) XpressNet messages derived from XNetMonFrame.
017 *
018 * @author Bob Jacobsen Copyright (C) 2002
019 * @author Paul Bender Copyright (C) 2004-2014
020 * @author Giorgio Terdina Copyright (C) 2007
021 */
022public class XNetMonPane extends jmri.jmrix.AbstractMonPane implements XNetListener {
023
024    protected XNetTrafficController tc = null;
025    protected XNetSystemConnectionMemo memo = null;
026
027    private List<XPressNetMessageFormatter> formatterList;
028
029
030    @Override
031    public String getTitle() {
032        return (Bundle.getMessage("MenuItemXNetCommandMonitor"));
033    }
034
035    @Override
036    public void initContext(Object context) {
037        if (context instanceof XNetSystemConnectionMemo) {
038            memo = (XNetSystemConnectionMemo) context;
039            tc = memo.getXNetTrafficController();
040            // connect to the TrafficController
041            tc.addXNetListener(~0, this);
042            try {
043                formatterList = new ArrayList<>();
044
045                Reflections reflections = new Reflections("jmri.jmrix.lenz.messageformatters");
046                Set<Class<? extends XPressNetMessageFormatter>> f = reflections.getSubTypesOf(XPressNetMessageFormatter.class);
047                for(Class<?> c : f){
048                    log.debug("Found formatter: {}", f.getClass().getName());
049                    Constructor<?> ctor = c.getConstructor();
050                    formatterList.add((XPressNetMessageFormatter) ctor.newInstance());
051                }
052            } catch (NoSuchMethodException | SecurityException | InstantiationException |
053                     IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
054                log.error("Error instantiating formatter", e);
055            }
056        }
057    }
058
059    /**
060     * Initialize the data source.
061     */
062    @Override
063    protected void init() {
064    }
065
066    @Override
067    public void dispose() {
068        // disconnect from the LnTrafficController
069        tc.removeXNetListener(~0, this);
070        // and unwind swing
071        super.dispose();
072    }
073
074    @Override
075    public void logMessage(String messagePrefix, String rawPrefix, Message message){
076        // display the raw data if requested
077        StringBuilder raw = new StringBuilder(rawPrefix);
078        if (rawCheckBox.isSelected()) {
079            raw.append(message.toString());
080        }
081
082        // display the decoded data
083        String text = formatterList.stream()
084                .filter(f -> f.handlesMessage(message))
085                .findFirst().map(f -> f.formatMessage(message))
086                .orElse(message.toString());
087        nextLine(messagePrefix + " " + text + "\n", raw.toString());
088    }
089
090    @Override
091    public synchronized void message(XNetReply l) { // receive an XpressNet message and log it
092        logMessage("","packet:",l);
093    }
094
095    /**
096     * Listen for the messages to the LI100/LI101
097     */
098    @Override
099    public synchronized void message(XNetMessage l) {
100        logMessage("", "packet:", l);
101    }
102
103    /**
104     * Handle a timeout notification
105     */
106    @Override
107    public void notifyTimeout(XNetMessage msg) {
108        log.debug("Notified of timeout on message {}", msg.toString());
109    }
110
111    /**
112     * Nested class to create one of these using old-style defaults
113     */
114    static public class Default extends jmri.util.swing.JmriNamedPaneAction {
115
116        public Default() {
117            super(Bundle.getMessage("MenuItemXNetCommandMonitor"), XNetMonPane.class.getName());
118            setContext(jmri.InstanceManager.
119                    getDefault(XNetSystemConnectionMemo.class));
120        }
121    }
122
123    private static final Logger log = LoggerFactory.getLogger(XNetMonPane.class);
124}