/*
* P2P-Radio - Peer to peer streaming system
* Project homepage: http://p2p-radio.sourceforge.net/
* Copyright (C) 2003-2004 Michael Kaufmann <hallo@michael-kaufmann.ch>
*
* ---------------------------------------------------------------------------
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ---------------------------------------------------------------------------
*/
package p2pradio.monitor;
import p2pradio.Messages;
import p2pradio.RemotePeer;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
public class TreeDataManager
{
private DefaultMutableTreeNode allPeers = new DefaultMutableTreeNode(Messages.getString("TreeDataManager.ALL_PEERS")); //$NON-NLS-1$
private DefaultMutableTreeNode connectedPeers = new DefaultMutableTreeNode(Messages.getString("TreeDataManager.CONNECTED_PEERS")); //$NON-NLS-1$
private DefaultMutableTreeNode connectingPeers = new DefaultMutableTreeNode(Messages.getString("TreeDataManager.CHANGING_PEERS")); //$NON-NLS-1$
private DefaultMutableTreeNode unconnectedPeers = new DefaultMutableTreeNode(Messages.getString("TreeDataManager.UNCONNECTED_PEERS")); //$NON-NLS-1$
private DefaultTreeModel treeModel;
private JTree tree;
// RemotePeer -> Node
private HashMap peers = new HashMap();
public TreeDataManager()
{
treeModel = new DefaultTreeModel(allPeers);
treeModel.insertNodeInto(connectedPeers, allPeers, allPeers.getChildCount());
treeModel.insertNodeInto(connectingPeers, allPeers, allPeers.getChildCount());
treeModel.insertNodeInto(unconnectedPeers, allPeers, allPeers.getChildCount());
}
public void setTree(JTree tree)
{
this.tree = tree;
}
public DefaultTreeModel getTreeModel()
{
return treeModel;
}
public void addPeer(RemotePeer supplier, RemotePeer peer)
{
DefaultMutableTreeNode supplierNode;
DefaultMutableTreeNode peerNode;
if (supplier == null)
{
if (!peers.containsKey(peer))
{
// Der Peer ist zum Netz hinzugekommen, hat
// aber noch keinen Zulieferer
peerNode = new DefaultMutableTreeNode(peer);
peers.put(peer, peerNode);
treeModel.insertNodeInto(peerNode, connectingPeers, connectingPeers.getChildCount());
}
else
{
// Der Peer ist schon bekannt, hat aber den
// Zulieferer verloren
peerNode = getNode(peer);
treeModel.removeNodeFromParent(peerNode);
treeModel.insertNodeInto(peerNode, connectingPeers, connectingPeers.getChildCount());
expandAllNodes(peerNode);
}
}
else
{
if (supplier.equals(peer))
{
throw new IllegalArgumentException(Messages.getString("TreeDataManager.SUPPLIER_AND_PEER_ARE_EQUAL")); //$NON-NLS-1$
}
if (peers.containsKey(supplier))
{
if (peers.containsKey(peer))
{
// Zulieferer und Peer sind schon bekannt.
// Den Peer unter den Zulieferer verschieben
supplierNode = getNode(supplier);
peerNode = getNode(peer);
// Ist das Kind korrekt unter dem Zulieferer eingetragen?
if (supplierNode.isNodeChild(peerNode))
{
return;
}
// Spezialfall: Peer ist ein Ahn des Zulieferers
if (supplierNode.isNodeAncestor(peerNode))
{
// Ast mit Zulieferer suchen
for (int i=0; i < peerNode.getChildCount(); i++)
{
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)peerNode.getChildAt(i);
if (childNode.isNodeDescendant(supplierNode))
{
treeModel.removeNodeFromParent(childNode);
treeModel.insertNodeInto(childNode, unconnectedPeers, unconnectedPeers.getChildCount());
expandAllNodes(childNode);
break;
}
}
}
treeModel.removeNodeFromParent(peerNode);
treeModel.insertNodeInto(peerNode, supplierNode, supplierNode.getChildCount());
expandAllNodes(peerNode);
}
else
{
// Der Zulieferer ist bekannt, der Peer nicht.
// Peer unter dem Zulieferer einf�gen
supplierNode = getNode(supplier);
peerNode = new DefaultMutableTreeNode(peer);
peers.put(peer, peerNode);
treeModel.insertNodeInto(peerNode, supplierNode, supplierNode.getChildCount());
}
}
else
{
if (peers.containsKey(peer))
{
// Der Zulieferer ist nicht bekannt, der Peer aber schon.
// Einen neuen Zulieferer erzeugen und den Peer unter diesen verschieben
supplierNode = new DefaultMutableTreeNode(supplier);
peers.put(supplier, supplierNode);
treeModel.insertNodeInto(supplierNode, unconnectedPeers, unconnectedPeers.getChildCount());
peerNode = getNode(peer);
treeModel.removeNodeFromParent(peerNode);
treeModel.insertNodeInto(peerNode, supplierNode, supplierNode.getChildCount());
expandAllNodes(peerNode);
}
else
{
// Zulieferer und Peer sind nicht bekannt
supplierNode = new DefaultMutableTreeNode(supplier);
treeModel.insertNodeInto(supplierNode, unconnectedPeers, unconnectedPeers.getChildCount());
peers.put(supplier, supplierNode);
peerNode = new DefaultMutableTreeNode(peer);
peers.put(peer, peerNode);
treeModel.insertNodeInto(peerNode, supplierNode, supplierNode.getChildCount());
}
}
}
// Neuen Knoten sichtbar machen
tree.scrollPathToVisible(new TreePath(peerNode.getPath()));
}
public void removePeer(RemotePeer peer)
{
DefaultMutableTreeNode peerNode;
// Gibt es den Knoten �berhaupt?
if (peers.containsKey(peer))
{
peerNode = getNode(peer);
// Ist es �berhaupt n�tig, etwas zu tun?
if (unconnectedPeers.isNodeChild(peerNode) && (peerNode.isLeaf()))
{
return;
}
// Alle Kinder von peer umh�ngen
while(peerNode.getChildCount() > 0)
{
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)peerNode.getChildAt(0);
treeModel.removeNodeFromParent(childNode);
treeModel.insertNodeInto(childNode, connectingPeers, connectingPeers.getChildCount());
expandAllNodes(childNode);
}
// Knoten umh�ngen
treeModel.removeNodeFromParent(peerNode);
treeModel.insertNodeInto(peerNode, unconnectedPeers, unconnectedPeers.getChildCount());
// Neuen Knoten sichtbar machen
tree.scrollPathToVisible(new TreePath(peerNode.getPath()));
}
}
public void addSource(RemotePeer source)
{
DefaultMutableTreeNode sourceNode;
if (peers.containsKey(source))
{
sourceNode = getNode(source);
// Ist die Quelle schon richtig eingetragen?
if (connectedPeers.isNodeChild(sourceNode))
{
return;
}
else
{
// Der Knoten ist schon bekannt, zu "Verbundene Peers" verschieben
treeModel.removeNodeFromParent(sourceNode);
treeModel.insertNodeInto(sourceNode, connectedPeers, connectedPeers.getChildCount());
expandAllNodes(sourceNode);
}
}
else
{
// Die Quelle ist neu
sourceNode = new DefaultMutableTreeNode(source);
peers.put(source, sourceNode);
treeModel.insertNodeInto(sourceNode, connectedPeers, connectedPeers.getChildCount());
expandAllNodes(sourceNode);
}
// Neuen Knoten sichtbar machen
tree.scrollPathToVisible(new TreePath(sourceNode.getPath()));
}
public void removeSource(RemotePeer source)
{
DefaultMutableTreeNode sourceNode;
if (peers.containsKey(source))
{
sourceNode = getNode(source);
// Ist es �berhaupt n�tig, etwas zu tun?
if (unconnectedPeers.isNodeChild(sourceNode) && (sourceNode.isLeaf()))
{
return;
}
// Alle Kinder von source umh�ngen
while(sourceNode.getChildCount() > 0)
{
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)sourceNode.getChildAt(0);
treeModel.removeNodeFromParent(childNode);
treeModel.insertNodeInto(childNode, connectingPeers, connectingPeers.getChildCount());
expandAllNodes(childNode);
}
// Quelle umh�ngen
treeModel.removeNodeFromParent(sourceNode);
treeModel.insertNodeInto(sourceNode, unconnectedPeers, unconnectedPeers.getChildCount());
// Neuen Knoten sichtbar machen
tree.scrollPathToVisible(new TreePath(sourceNode.getPath()));
}
}
protected DefaultMutableTreeNode getNode(RemotePeer peer)
{
return (DefaultMutableTreeNode)peers.get(peer);
}
private void expandAllNodes(DefaultMutableTreeNode node)
{
expandAllNodes(new TreePath(node.getPath()));
}
private void expandAllNodes(TreePath path)
{
// Klappt "node" und alle Kinder rekursiv auf
TreeNode node = (TreeNode)path.getLastPathComponent();
if (node.isLeaf())
{
// Kann nur ausserhalb der Rekursion geschehen (direkter Aufruf)
tree.expandPath(path.getParentPath());
}
else
{
boolean alreadyExpanded = false;
for (int i=0; i < node.getChildCount(); i++)
{
if (!node.getChildAt(i).isLeaf())
{
alreadyExpanded = true;
expandAllNodes(path.pathByAddingChild(node.getChildAt(i)));
}
}
// Der Knoten muss nur aufgeklappt werden, wenn er nicht
// schon indirekt durch einen Kindsknoten aufgeklappt worden ist
if (!alreadyExpanded)
{
tree.expandPath(path);
}
}
}
public void removeUnconnectedPeers()
{
while (unconnectedPeers.getChildCount() > 0)
{
DefaultMutableTreeNode node = (DefaultMutableTreeNode)unconnectedPeers.getChildAt(0);
RemotePeer peer = (RemotePeer)node.getUserObject();
peers.remove(peer);
treeModel.removeNodeFromParent(node);
}
}
public void clear()
{
peers.clear();
while (connectedPeers.getChildCount() > 0)
{
treeModel.removeNodeFromParent((DefaultMutableTreeNode)connectedPeers.getChildAt(0));
}
while (connectingPeers.getChildCount() > 0)
{
treeModel.removeNodeFromParent((DefaultMutableTreeNode)connectingPeers.getChildAt(0));
}
while (unconnectedPeers.getChildCount() > 0)
{
treeModel.removeNodeFromParent((DefaultMutableTreeNode)unconnectedPeers.getChildAt(0));
}
}
}