package wdv.kg; import java.awt.FontMetrics; import java.util.ArrayList; import java.util.Iterator; import wdv.util.Vec4; /** * Represent a graph. * * Created: November 11, 2002, 5:03 PM * * @author L. Van Warren * @version 2011 © 2002-2011 * * @see Node * @see Edge */ public class Graph { public static final int STARTSIZE = 32; public static JAppletA jAppletA; public static FontMetrics currentFontMetrics; // public static ArrayList nodeList = new ArrayList(STARTSIZE); public static ArrayList edgeList = new ArrayList(STARTSIZE); // public static int graphID = 0; public static int newNodeID = 0; public static int newEdgeID = 0; /** * This class is a static singleton, make sure on one instantiates it. * */ private Graph() { } public static void init(JAppletA jAppletA) { Graph.jAppletA = jAppletA; Graph.delete(); GraphColor.buildArcColorTable(); currentFontMetrics = jAppletA.getFontMetrics(GraphDisplay.currentFont); } /** * */ public static void finish() { Graph.computeAdjacency(); Graph.graphID++; // JAppletA.jNodeTableListener = new NodeTableListener(jAppletA); JAppletA.jNodeTable.getModel().addTableModelListener(JAppletA.jNodeTableListener); NodeTableListener.jNodeTableModel.fireTableDataChanged(); // JAppletA.jEdgeTableListener = new EdgeTableListener(jAppletA); JAppletA.jEdgeTable.getModel().addTableModelListener(JAppletA.jEdgeTableListener); EdgeTableListener.jEdgeTableModel.fireTableDataChanged(); } /** * Lock node names. * */ public static void lockNodeNames() { for (Node node : nodeList) { node.lockName(); } } /** * Unlock node names. * */ public static void unlockNodeNames() { for (Node node : nodeList) { node.unlockName(); } } /** * Lock node names. * */ public static void lockEdgeNames() { for (Edge edge : edgeList) { edge.lockName(); } } /** * Unlock node names. * */ public static void unlockEdgeNames() { for (Edge edge : edgeList) { edge.unlockName(); } } /** * Reset display of numbered instances on flag change. * */ public static void resetNumberedInstances() { for (Node node : nodeList) { node.setNumberedInstance(); } for (Edge edge : edgeList) { edge.setNumberedInstance(); } } /** * */ public static void clear() // probably not the right name for this! { WindowManager.clearTitleBlock(); JAppletA.jComboBoxNavigation.insertItemAt("", 0); JAppletA.jComboBoxNavigation.setSelectedIndex(0); NodeTableListener.jNodeTableModel.checkLowTable(true); EdgeTableListener.jEdgeTableModel.checkLowTable(true); } /** * Clear the Graph nodeList and edgeList by allocating new ones. * The garbage collector takes care of the rest. */ public static void delete() { JAppletA.jPanelA.removeAll(); Graph.nodeList = new ArrayList(STARTSIZE); Graph.edgeList = new ArrayList(STARTSIZE); UniqueID.resetNodeAndEdgeIDGenerator(); } /** * Find a node in Graph by name. * @param name * @return node index */ public static Node getNodeByName(String name) { for (Node node : nodeList) { if (node.getName().equals(name)) { return node; } } return null; } /** * Find an edge in Graph by name. * @param name * @return edge */ public static Edge getEdgeByName(String name) { for (Edge edge : edgeList) { if (edge.getName().equals(name)) { return edge; } } return null; } /** * Find a node index in Graph by name. * @param name * @return node index */ public static int getNodeIndexByName(String name) { for (int i = 0; i < nodeList.size(); i++) { Node node = nodeList.get(i); if (node.getName().equals(name)) { return i; } } return -1; } /** * Add node to Graph, creating a named instance of same. * @param name * @param x * @param y * @return node index */ public static Node addNode(String name, double x, double y) { Node node = new Node(name, x, y); nodeList.add(node); JAppletA.jPanelA.add(node.getNameField()); if (JAppletA.jNodeTableListener != null) { NodeTableListener.jNodeTableModel.fireTableStructureChanged(); } return (node); } /** * * @param nodeName * @param URLString */ public static void addNodeLink(String nodeName, String URLString) { for (Node node : nodeList) { if (node.getName().equals(nodeName)) { node.URLString = URLString; } } } /** * * @param nodeName * @param imageString */ public static void addNodeImage(String nodeName, String imageString) { for (Node node : nodeList) { if (node.getName().equals(nodeName)) { node.imageString = imageString; node.bufferedImage = IconProcess.readImage(node.imageString); } } } /** * * @param nodeName * @param iconString */ public static void addNodeIcon(String nodeName, String iconString) { for (Node node : nodeList) { if (node.getName().equals(nodeName)) { node.iconString = iconString; node.imageIcon = IconProcess.readIcon(node.iconString); } } } /** * * @param name * @param position * @param offset * @return node created. */ public static Node nodeCreate(String name, Vec4 position, Vec4 offset) { if (name == null) { name = "newNode" + Graph.newNodeID; Graph.newNodeID++; } Node node = Graph.addNode(name, position.x[0], position.x[1]); offset.set4(node.position.sub3(position)); node.position.set4(position.add3(offset)); GraphSelect.incrementNodeSelectionLevel(node); return (node); } /** * * @param node */ public static void nodeDelete(Node node) // and delete connected edges... { for (Iterator iteratorEdge = edgeList.iterator(); iteratorEdge.hasNext();) { Edge edge = iteratorEdge.next(); Node nodeA = edge.a; Node nodeB = edge.b; if (node.equals(nodeA) || node.equals(nodeB)) { JAppletA.jPanelA.remove(edge.getNameField()); iteratorEdge.remove(); } } // remove the JTextField from the display. if (node != null) { JAppletA.jPanelA.remove(node.getNameField()); // remove the node from the nodelist nodeList.remove(node); } } /** * Add edge to a Graph, while creating a named instance of same. * * The arguments to this method are in the form of aRb where: * * @param nodeNameA - name of node a. * @param R - name of edge, the relationship between a and b and * @param nodeNameB is the name of node b. */ public static void addEdge(String nodeNameA, String R, String nodeNameB) { Node nodeA = getNodeByName(nodeNameA); if (nodeA == null) { UserIO.println("addEdge: node [" + nodeNameA + "] is not declared, cannot create edge."); return; } Node nodeB = getNodeByName(nodeNameB); if (nodeB == null) { UserIO.println("addEdge: node [" + nodeNameB + "] is not declared, cannot create edge."); return; } Edge edge = new Edge(nodeA, R, nodeB); edgeList.add(edge); JAppletA.jPanelA.add(edge.getNameField()); if (JAppletA.jEdgeTableListener != null) { EdgeTableListener.jEdgeTableModel.fireTableStructureChanged(); } return; } public static void edgeCreate(String name, Node nodeA, Node nodeB) { if (name == null) { name = "newEdge" + Graph.newEdgeID; Graph.newEdgeID++; } Graph.addEdge(nodeA.getName(), name, nodeB.getName()); GraphSelect.incrementEdgeSelectionLevel(Graph.edgeList.get(Graph.edgeList.size() - 1)); return; } /** * * @param edge */ public static void edgeDeletor(Edge edge) // and delete connected edges... { for (Iterator iteratorEdge = edgeList.iterator(); iteratorEdge.hasNext();) { Edge currEdge = iteratorEdge.next(); if (edge.equals(currEdge)) { UserIO.println("edge " + edge.getName() + ", is, deleted"); JAppletA.jPanelA.remove(currEdge.getNameField()); iteratorEdge.remove(); } } } /** * * @param edge */ public static void edgeDeletorByRelationship(Edge edge) // and delete connected edges... { for (Iterator iteratorEdge = edgeList.iterator(); iteratorEdge.hasNext();) { Edge currEdge = iteratorEdge.next(); if (edge.getNameField().getText().equals(currEdge.getNameField().getText())) { JAppletA.jPanelA.remove(currEdge.getNameField()); iteratorEdge.remove(); } } } /** * Compute adjacency list for nodes in the Graph, * that is for each node, what nodes are one hop away? * * the naive algorithm is: * for each pair of nodes, is there an edge between them? * if so, add that node to the adjacency list * this algorithm is quadratic in the number of nodes * * a smarter algorithm is * for each edge * add each respective node to the other's adjacency list. * this algorithm is linear in the number of edges * for a sparse Graph, it is also approximately linear in the number of nodes. */ public static void computeAdjacency() { for (Edge edge : edgeList) { Node nodeA = edge.a; Node nodeB = edge.b; nodeA.adjList.add(nodeB); nodeB.adjList.add(nodeA); } } public static void find(String string) { for (Node node : nodeList) { if (node.getName().equals(string)) { node.selectionLevel++; } } for (Edge edge : edgeList) { if (edge.getNameField().getText().equals(string)) { edge.selectionLevel++; } } NodeTableListener.jNodeTableModel.fireTableDataChanged(); EdgeTableListener.jEdgeTableModel.fireTableDataChanged(); } }