package org.jcon.ba.edit;

import org.jcon.util.msg.MessageSource;
import org.jcon.util.msg.MessageRouter;
import java.util.Vector;

/**
 * Represents a "node" in a Message chain. Note the unusual
 * recursive constructor.
 *
 * @author Jack Harich
 */
public class MessageNode {

//---------- Private Fields ------------------------------
private String      eventName; // Same for all in tree
private Object      instance;  // MessageSource and/or MessageListener
private MessageNode parent;    // null if root
private int         level;     // 0 for root

// Contains MessageNodes listening to eventName
private Vector listeners = new Vector();

//---------- Initialization ------------------------------
/**
 * Creates a MessageNode for the eventName and instance.
 * The instance should be a MessageSource and/or
 * MessageListener to make sense. RECURSIVE.
 */
public MessageNode(String eventName, Object instance,
        MessageNode parent) {
    this.eventName = eventName;
    this.instance = instance;
    this.parent = parent;
    if (parent != null) level = parent.getLevel() + 1;

    // End recursion if instance is not a MessageSource
    if (! (instance instanceof MessageSource)) {
        return;
    }
    // Get listeners for eventName in source
    MessageSource source = (MessageSource)instance;
    MessageRouter router = source.getMessageRouter();
    if (! router.hasListener(eventName)) return;

    Vector sourceListeners = router.getEventListeners(eventName);

    // Recurse on each listener. There may be none.
    for (int i = 0; i < sourceListeners.size(); i++) {
        Object listener = sourceListeners.elementAt(i);
        MessageNode node = new MessageNode(eventName,
            listener, this); // RECURSE
        listeners.addElement(node);
    }
}
//---------- Public Methods ------------------------------
public Object getInstance() {
    return instance;
}
public Vector getListeners() {
    return listeners;
}
public int getLevel() {
    return level;
}
/**
 * Loads all the nodes in the branch starting at this node.
 * If this node is the root then this loads the entire tree.
 */
public Vector loadBranch() {
    Vector nodes = new Vector();
    addNodeChildren(this, nodes);
    return nodes;
}
//---------- Private Methods -----------------------------
// RECURSIVE
private static void addNodeChildren(MessageNode node, Vector nodes) {
    nodes.addElement(node);
    Vector children = node.getListeners();
    // Recursion stops if no children
    for (int i = 0; i < children.size(); i++) {
        MessageNode child = (MessageNode)children.elementAt(i);
        addNodeChildren(child, nodes);
    }
}
//--- Std
private static void print(String text) {
    System.out.println("MessageNode" + text);
}

} // End class
