001package jmri.jmrit.automat; 002 003import java.util.ArrayList; 004 005/** 006 * A singlet providing access to information about existing Automat instances. 007 * <p> 008 * It might not always be a singlet, however, so for now we're going through an 009 * explicit instance() reference. 010 * <p> 011 * This can be invoked from various threads, so switches to the Swing thread to 012 * notify its own listeners. 013 * 014 * @author Bob Jacobsen Copyright (C) 2004, 2007 015 */ 016public class AutomatSummary { 017 018 private AutomatSummary() { 019 } 020 021 static volatile private AutomatSummary self = null; 022 023 static public AutomatSummary instance() { 024 if (self == null) { 025 self = new AutomatSummary(); 026 } 027 return self; 028 } 029 030 private final ArrayList<AbstractAutomaton> automats = new ArrayList<>(); 031 032 java.beans.PropertyChangeSupport prop = new java.beans.PropertyChangeSupport(this); 033 034 public void removePropertyChangeListener(java.beans.PropertyChangeListener p) { 035 prop.removePropertyChangeListener(p); 036 } 037 038 public void addPropertyChangeListener(java.beans.PropertyChangeListener p) { 039 prop.addPropertyChangeListener(p); 040 } 041 042 /** 043 * A newly-created AbstractAutomaton instance uses this method to notify 044 * interested parties of its existence. 045 * 046 * @param a the automaton to register 047 */ 048 public void register(AbstractAutomaton a) { 049 synchronized (automats) { 050 automats.add(a); 051 } 052 053 //notify length changed 054 notify("Insert", null, indexOf(a)); 055 056 } 057 058 /** 059 * Just before exiting, an AbstractAutomaton instance uses this method to 060 * notify interested parties of its departure. 061 * 062 * @param a the automaton to remove 063 */ 064 public void remove(AbstractAutomaton a) { 065 int index = indexOf(a); 066 067 synchronized (automats) { 068 automats.remove(a); 069 } 070 071 //notify length changed 072 notify("Remove", null, index); 073 } 074 075 public ArrayList<AbstractAutomaton> getAutomats() { 076 return new ArrayList<>(automats); 077 } 078 079 public int length() { 080 int length; 081 synchronized (automats) { 082 length = automats.size(); 083 } 084 return length; // debugging value 085 } 086 087 public AbstractAutomaton get(int i) { 088 AbstractAutomaton retval; 089 090 synchronized (automats) { 091 retval = automats.get(i); 092 } 093 094 return retval; 095 } 096 097 /** 098 * Provide a convenience method to look up a managed object by its name. 099 * 100 * @since 1.7.3 101 * @param name Name of the automat to be located 102 * @return null if name not found 103 */ 104 public AbstractAutomaton get(String name) { 105 AbstractAutomaton a; 106 synchronized (automats) { 107 for (int i = 0; i < length(); i++) { 108 a = automats.get(i); 109 if (a.getName().equals(name)) { 110 return a; 111 } 112 } 113 } 114 return null; 115 } 116 117 public int indexOf(AbstractAutomaton a) { 118 int retval; 119 synchronized (automats) { 120 retval = automats.indexOf(a); 121 } 122 return retval; 123 } 124 125 /** 126 * An AbstractAutomaton instance uses this method to notify interested 127 * parties that it's gone around its handle loop again. 128 * 129 * @param a the looping automaton 130 */ 131 public void loop(AbstractAutomaton a) { 132 int i; 133 synchronized (automats) { 134 i = automats.indexOf(a); 135 } 136 notify("Count", null, i); 137 } 138 139 void notify(String property, Object arg1, Object arg2) { 140 Runnable r = new Notifier(property, arg1, arg2); 141 javax.swing.SwingUtilities.invokeLater(r); 142 } 143 144 private class Notifier implements Runnable { 145 146 Notifier(String property, Object arg1, Object arg2) { 147 this.property = property; 148 this.arg1 = arg1; 149 this.arg2 = arg2; 150 } 151 Object arg1; 152 Object arg2; 153 String property; 154 155 @Override 156 public void run() { 157 prop.firePropertyChange(property, arg1, arg2); 158 } 159 160 } 161}