001package jmri.jmrix.rps; 002 003import java.util.Vector; 004import org.slf4j.Logger; 005import org.slf4j.LoggerFactory; 006 007/** 008 * Distributes Readings and the Measurements calculated from them. 009 * 010 * @author Bob Jacobsen Copyright (C) 2006, 2008 011 */ 012public class Distributor { 013 014 /** 015 * Request being informed when a new Reading is available. 016 * @param l the reading listener to add. 017 */ 018 public void addReadingListener(ReadingListener l) { 019 // add only if not already registered 020 if (!readingListeners.contains(l)) { 021 readingListeners.addElement(l); 022 } 023 } 024 025 /** 026 * Request to no longer be informed when new Readings arrive. 027 * @param l the reading listener to remove. 028 */ 029 public void removeReadingListener(ReadingListener l) { 030 if (readingListeners.contains(l)) { 031 readingListeners.removeElement(l); 032 } 033 } 034 035 /** 036 * Invoked when a new Reading is created. 037 * @param s the reading. 038 */ 039 @SuppressWarnings("unchecked") 040 public void submitReading(Reading s) { 041 // make a copy of the listener vector to synchronized not needed for transmit 042 Vector<ReadingListener> v; 043 synchronized (this) { 044 v = (Vector<ReadingListener>) readingListeners.clone(); 045 } 046 log.debug("notify {} ReadingListeners about item", v.size()); 047 // forward to all listeners 048 int cnt = v.size(); 049 for (int i = 0; i < cnt; i++) { 050 ReadingListener client = v.elementAt(i); 051 javax.swing.SwingUtilities.invokeLater(new ForwardReading(s, client)); 052 } 053 } 054 055 /** 056 * Request being informed when a new Measurement is available. 057 * @param l the listener to add. 058 */ 059 public void addMeasurementListener(MeasurementListener l) { 060 // add only if not already registered 061 if (!measurementListeners.contains(l)) { 062 measurementListeners.addElement(l); 063 } 064 } 065 066 /** 067 * Request to no longer be informed when new Measurements arrive. 068 * @param l the listener to remove. 069 */ 070 public void removeMeasurementListener(MeasurementListener l) { 071 if (measurementListeners.contains(l)) { 072 measurementListeners.removeElement(l); 073 } 074 } 075 076 /** 077 * Invoked when a new Measurement is created. 078 * @param s the measurement. 079 */ 080 @SuppressWarnings("unchecked") 081 public void submitMeasurement(Measurement s) { 082 // make a copy of the listener vector to synchronized not needed for transmit 083 Vector<MeasurementListener> v; 084 synchronized (this) { 085 v = (Vector<MeasurementListener>) measurementListeners.clone(); 086 } 087 log.debug("notify {} MeasurementListeners about item", v.size()); 088 // forward to all listeners 089 int cnt = v.size(); 090 for (int i = 0; i < cnt; i++) { 091 MeasurementListener client = v.elementAt(i); 092 javax.swing.SwingUtilities.invokeLater(new ForwardMeasurement(s, client)); 093 } 094 } 095 096 static volatile private Distributor instance = null; 097 098 public static Distributor instance() { 099 if (instance == null) { 100 instance = new Distributor(); 101 } 102 return instance; 103 } 104 105 //////////////////////////// 106 // Implementation details // 107 //////////////////////////// 108 final private Vector<ReadingListener> readingListeners = new Vector<ReadingListener>(); 109 final private Vector<MeasurementListener> measurementListeners = new Vector<MeasurementListener>(); 110 111 /** 112 * Forward the Reading from the Swing thread. 113 */ 114 static class ForwardReading implements Runnable { 115 116 Reading s; 117 ReadingListener client; 118 119 ForwardReading(Reading s, ReadingListener client) { 120 this.s = s; 121 this.client = client; 122 } 123 124 @Override 125 public void run() { 126 client.notify(s); 127 } 128 } 129 130 /** 131 * Forward the Measurement from the Swing thread. 132 */ 133 static class ForwardMeasurement implements Runnable { 134 135 Measurement s; 136 MeasurementListener client; 137 138 ForwardMeasurement(Measurement s, MeasurementListener client) { 139 this.s = s; 140 this.client = client; 141 } 142 143 @Override 144 public void run() { 145 client.notify(s); 146 } 147 } 148 149 private final static Logger log = LoggerFactory.getLogger(Distributor.class); 150 151}