package vcb.vt.app;
import vcb.engine.part.Receiver;
import vcb.engine.tron.Datatron;
import vcb.gen.io.DatatronStore;
import vcb.gen.util.ListOne;
import java.util.HashMap;
/**
* This provides nodes with standard services, using the Context
* Pattern. Not all nodes will use all services.
*
* Creation using the constructor creates a new instance with
* an event registry. Creating a new instance with the create
* method copies the registry and other properties to the new
* instance. This allows many nodes to share the same properties
* and event registry.
*
* This allows the system designer to design a tree of subsystems.
* Each subsystem has a NodeContext. They all share certain
* services, the most powerful being the event registry, which
* allows a node anywhere in the system to send an event to any
* other node(s) in the system.
*
* @author Jack Harich
*/ // import vcb.vt.app.NodeContext;
public class NodeContext {
//---------- Internal Fields -------------------------------------
//----- These are all one per system
protected DatatronStore userConfig;
protected WindowMgr windowMgr = new WindowMgr();
protected PartStore partStore = new PartStore();
// Key = String event name, Object = ListOne of Receivers
protected HashMap listeners = new HashMap();
//----- These vary per node protected Receiver receiver;
//---------- Initialization --------------------------------------
/**
* Creates a new instance. All aguments are required. Note that
* create(...) must be used to set the receiver property.
*/
public NodeContext(DatatronStore userConfig) {
this.userConfig = userConfig;
}
/**
* Creates a new context from this one, replacing the old receiver
* (if any) with the new one provided, which may be null.
*/
public NodeContext create(Receiver receiver) {
NodeContext context = new NodeContext(userConfig);
context.receiver = receiver;
context.windowMgr = windowMgr;
context.partStore = partStore;
context.listeners = listeners;
return context;
}
//---------- Public Methods --------------------------------------
//----- Getters
/**
* Returns the user config store.
*/
public DatatronStore getUserConfig() {
return userConfig;
}
/**
* Returns the window manager.
*/
public WindowMgr getWindowMgr() {
return windowMgr;
}
/**
* Returns the part store.
*/
public PartStore getPartStore() {
return partStore;
}
/**
* Returns the receiver, which is null if none.
*/
public Receiver getReceiver() {
return receiver;
}
//----- Events
/**
* Registers the listener for the eventName.
*/
public void addContextListener(String eventName, Receiver listener) {
//print(".addListener() - eventName = " + eventName + ", " + this);
ListOne list = (ListOne)listeners.get(eventName);
if (list == null) {
list = new ListOne();
listeners.put(eventName, list);
}
list.add(listener);
}
/**
* Unregisters the listener for the eventName.
*/
public void removeContextListener(String eventName, Receiver listener) {
ListOne list = (ListOne)listeners.get(eventName);
if (list != null) {
list.remove(listener);
if (list.isEmpty()) listeners.remove(eventName);
}
}
/**
* Sends the event to all registered listeners for the eventName.
* The receive(String inpin, Datatron datatron) method is called
* on all listeners, since they implement Receiver.
*
* For safety the list of receivers is cloned before the multicast,
* allowing receivers to be safely added or removed during the multicast.
*/
public void fireContextEvent(String eventName, Datatron datatron) {
//print(".fireEvent() - Entered, eventName = " + eventName + ", " + this);
ListOne list = (ListOne)listeners.get(eventName);
if (list == null) return;
synchronized(this) {
list = (ListOne)list.clone();
}
//print(".fireEvent() - Multicasting to " + list.size() + " listeners");
Receiver receiver;
for (int i = list.size(); i >= 1; i--) {
receiver = (Receiver)list.get(i);
receiver.receive(eventName, datatron);
}
}
//---------- Standard --------------------------------------------
private static void print(String text) {
System.out.println("NodeContext" + text);
}
} // End class