001package jmri.jmris; 002 003import java.beans.PropertyChangeEvent; 004import java.beans.PropertyChangeListener; 005import java.io.IOException; 006import java.util.HashMap; 007import java.util.Map; 008import jmri.InstanceManager; 009import jmri.JmriException; 010import jmri.Reporter; 011 012/** 013 * Abstract interface between the a JMRI reporter and a network connection 014 * 015 * @author Paul Bender Copyright (C) 2010 016 * @author Randall Wood Copyright (C) 2013 017 */ 018abstract public class AbstractReporterServer { 019 020 private final HashMap<String, ReporterListener> reporters; 021 022 public AbstractReporterServer() { 023 reporters = new HashMap<>(); 024 } 025 026 /* 027 * Protocol Specific Abstract Functions 028 */ 029 abstract public void sendReport(String reporter, Object r) throws IOException; 030 031 abstract public void sendErrorStatus(String reporter) throws IOException; 032 033 abstract public void parseStatus(String statusString) throws JmriException, IOException; 034 035 synchronized protected void addReporterToList(String reporterName) { 036 if (!reporters.containsKey(reporterName)) { 037 reporters.put(reporterName, new ReporterListener(reporterName)); 038 Reporter reporter = InstanceManager.getDefault(jmri.ReporterManager.class).getReporter(reporterName); 039 if(reporter!=null) { 040 reporter.addPropertyChangeListener(reporters.get(reporterName)); 041 } 042 } 043 } 044 045 synchronized protected void removeReporterFromList(String reporterName) { 046 if (reporters.containsKey(reporterName)) { 047 Reporter reporter = InstanceManager.getDefault(jmri.ReporterManager.class).getReporter(reporterName); 048 if(reporter!=null) { 049 reporter.removePropertyChangeListener(reporters.get(reporterName)); 050 } 051 reporters.remove(reporterName); 052 } 053 } 054 055 public Reporter initReporter(String reporterName) throws IllegalArgumentException { 056 Reporter reporter = InstanceManager.getDefault(jmri.ReporterManager.class).provideReporter(reporterName); 057 this.addReporterToList(reporterName); 058 return reporter; 059 } 060 061 /* 062 * Set the report state of a reporter 063 * 064 * @parm reporterName - the name of a reporter 065 * @parm r - the object containing the report (currently a string). 066 */ 067 public void setReporterReport(String reporterName, Object r) { 068 Reporter reporter; 069 // load address from reporterAddrTextField 070 try { 071 addReporterToList(reporterName); 072 reporter = InstanceManager.getDefault(jmri.ReporterManager.class).getReporter(reporterName); 073 if (reporter == null) { 074 log.error("Reporter {} is not available", reporterName); 075 } else { 076 log.debug("about to set reporter State"); 077 reporter.setReport(r); 078 } 079 } catch (Exception ex) { 080 log.error("set reporter report", ex); 081 } 082 } 083 084 public void dispose() { 085 for (Map.Entry<String, ReporterListener> entry: this.reporters.entrySet()) { 086 Reporter reporter = InstanceManager.getDefault(jmri.ReporterManager.class).getReporter(entry.getKey()); 087 if(reporter!=null) { 088 reporter.removePropertyChangeListener(entry.getValue()); 089 } 090 } 091 this.reporters.clear(); 092 } 093 094 class ReporterListener implements PropertyChangeListener { 095 096 ReporterListener(String reporterName) { 097 name = reporterName; 098 reporter = InstanceManager.getDefault(jmri.ReporterManager.class).getReporter(reporterName); 099 } 100 101 // update state as state of reporter changes 102 @Override 103 public void propertyChange(PropertyChangeEvent e) { 104 // If the Commanded State changes, show transition state as "<inconsistent>" 105 if (e.getPropertyName().equals("currentReport")) { 106 var n = e.getNewValue(); 107 String now = null; // current report might be null 108 if ( n != null ){ 109 now = n.toString(); 110 } 111 try { 112 sendReport(name, now); 113 } catch (IOException ie) { 114 log.debug("Error Sending Status"); 115 // if we get an error, de-register 116 reporter.removePropertyChangeListener(this); 117 removeReporterFromList(name); 118 } 119 } 120 } 121 String name = null; 122 Reporter reporter = null; 123 } 124 125 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AbstractReporterServer.class); 126 127}