Get started with an open-source, Swing-based library for creating graphs Jeroen van Bergen introduces JGraph, a popular open source library for creating graphs in Java applications. Creating a Wikipedia browser is an easy way to get started with JGraph’s Swing-MVC programming model. Once you’re familiar with JGraph you can consider the many other uses for graphs in your Java applications, including some that apply to Java application development.Most application developers know that a picture can say more than a thousand words. A graphical representation of data, for instance, can be easier to grasp than the raw data itself. Graphs are used in many fields to convey the meaning of data in a compact form with high impact. The ability to display information in graph format is an essential component of many Java applications.In this article I’ll show you how to use JGraph, an open source, Swing-based library for creating graphs. You can use JGraph to create graphs for almost any kind of application, and it is applicable to both desktop and server-side Java applications. As an exercise, I’ll walk you through the process of creating a small browser that shows a graph of a lemma and its links to other lemmata on Wikipedia. (A lemma is the word under which a set of related dictionary or encyclopedia entries appears.) When a user clicks on a lemma in the Wikipedia browser it is displayed along with its links.Once you’ve built the Wikipedia browser and have a good grasp of how JGraph works, I’ll suggest some of the ways graphs could actually be useful to Java developers; including a graphing application to simplify the creation and management of XML configuration files. The basic JGraph library is available for free under the LGPL or Mozilla Public License. You should download it now so that you can build the Wikipedia browser along with me. To install JGraph you’ll simply need to add its jar file to your classpath. No additional libraries are needed to use JGraph. Note that this article assumes you are somewhat familiar with Swing programming, although you need not be an expert.The Wikipedia browserThe actual implementation of the Wikipedia browser is simple, though it enables a user to explore the relationships between Wikipedia lemmata. The browser application can be broken down to the following subtasks:Read a set of configuration data.Retrieve the raw data.Extract the data to display.Represent the actual data in the form of a graph.Interact with the user to allow exploration.In the first three steps you are laying the groundwork for the Wikipedia browser by setting up the data to be graphed. In the last two steps you create the graph and add its functionality. I’ll go through all the steps in the sections that follow. Read, retrieve, and extract the dataYou will start by creating a Properties object to hold the configuration data. The object can easily be instantiated from a file as shown in Listing 1.Listing 1. Instantiating the Properties object// Load the configuration Properties configuration = null; try { configuration = new Properties(); configuration.load(new FileInputStream(args[0])); } catch (IOException e) { // handle exception } Note that the configuration contains an optional description of a proxy server and two items describing the first URL to retrieve. One of these is a URL prefix that is used to create a URL from just the name of an article. The other item is the name of the first lemma to be retrieved. Once you know where to get the data, you can issue an HTTP GET request to do so. In Listing 2 I’ve used the Apache Jakarta Commons HttpClient to retrieve data from the Wikipedia server. Listing 2. Using HttpClient to retrieve dataHttpClient httpClient = new HttpClient(); urlPrefix = configuration.getProperty("url_prefix"); if (configuration.getProperty("proxyhost") != null) { httpClient.getHostConfiguration().setProxy(configuration.getProperty("proxyhost"), Integer.parseInt(configuration.getProperty("proxyport"))); } String url = urlPrefix + name; GetMethod getMethod = new GetMethod(url); try { System.out.println("Fetching URL " + url + "..."); httpClient.executeMethod(getMethod); } catch (IOException e) { // handle exception throw e; } BufferedReader responseReader = null; StringBuilder content = new StringBuilder(); try { responseReader = new BufferedReader(new InputStreamReader(getMethod.getResponseBodyAsStream())); String currentLine = null; while ((currentLine = responseReader.readLine()) != null) { content.append(currentLine); } responseReader.close(); } catch (IOException e) { // handle exception } The content variable now holds the raw HTML of the Wikipedia lemma. Your next step is to extract the data you want. Because you are interested only in the links from one lemma to other lemmata, you need to isolate the links. Furthermore, not all links are interesting because some of them point to help pages, talk pages, or other internal Wikipedia resources. You’ll need to filter these so that they don’t clutter the view. The configuration in Listing 3 holds a list of Strings to filter out unwanted links.Listing 3. Using Strings to filter out unwanted data String[] ignoreParts; ignoreParts =configuration.getProperty("ignore").split(","); List<String> lemmaLinks = new ArrayList<String>(); int currentIndex = 0; // All links to other lemmata start with "/wiki Note the double quote, it distinguishes internal from interwiki links. while (lemma.indexOf(""/wiki", currentIndex) != -1) { int start = lemma.indexOf(""/wiki", currentIndex) + 7; int end = lemma.indexOf(""", start); String lemmaLink = lemma.substring(start, end); currentIndex = end; boolean ignoreCurrentLink = false; for (String linkPart : ignoreParts) { if (lemmaLink.contains(linkPart)) { ignoreCurrentLink = true; break; } } if (! ignoreCurrentLink) { lemmaLinks.add(lemmaLink); } } return lemmaLinks; Finally, you create a Lemma object to hold the data. This object is just a value object, it is not capable of performing any actions on the lemma. You will use the Lemma object as the basis for the graph. The Lemma object has the public interface shown in Listing 4.Listing 4. Public interface Lemmapublic interface Lemma { String getName(); List<String> getLinks(); } Note that the interface represents the data you want to display. For now you want to display only the relationship between this lemma and other lemmata, so you’re not interested in the actual text of the lemma. Not displaying the text makes it easer to show the relationships between lemma and lemmata. As an exercise, you might try adding another pane to this program, that displays the textual content of the lemma. Create the graphBefore diving into creating graphical elements for the Wikipedia browser, let’s make sure we agree on the definition of a graph: a graph is nothing but a collection of nodes with edges connecting them. It may seem simplistic, but that is all you need for now. In the Wikipedia browser, a Lemma will be represented as a node and a link will be represented as an edge that connects to a node. To summarize: the current lemma is displayed as a node, the link to another lemma as an edge, and any lemma the current lemma links to is also displayed as a node.Armed with this knowledge you can safely begin using the JGraph library to map and display the links between lemma and lemmata on Wikipedia. The groundwork for the graph is shown in Listing 5.Listing 5. Creating the model and the view GraphModel model = new DefaultGraphModel(); JGraph graph = new JGraph(model); The MVC design pattern in JGraphJGraph uses the model-view-controller design pattern, which should be familiar to most Java developers. In this case, you will use the default model that is provided with the JGraph library, the JGraph class. JGraph is the central class of the JGraph package. It extends Swing’s JComponent and thus can be used to actually show the graph.Once you have a model you can populate it with data (as shown in Listing 8). In JGraph terminology all elements of a graph are cells. You will first create cells to represent the lemmata and the edges connecting the lemmata. In Listing 6 I have created the cells first and then added them all at once to the graph.Listing 6. Creating cells and adding them to the JGraph // A List of the cells that will be added to the model List<DefaultGraphCell> cells = new ArrayList<DefaultGraphCell>(); // Create a cell for the Lemma DefaultGraphCell lemmaCell = createCell(lemma.getName(), width * numberOfLinks/2, 250); cells.add(lemmaCell); The next step is to loop over the links, create a node for every lemma that your lemma links to, and connect the two nodes with an edge, as shown in Listing 7. Listing 7. Creating and connecting nodes and edges double x = 0; double y; for (String link : lemma.getLinks()) { if (lemma.getLinks().indexOf(link) % 2 == 0) { y = 50; } else { y = 450; } DefaultGraphCell currentLinkedLemma = createCell(link, x, y); DefaultGraphCell currentLink = createEdge(lemmaCell, currentLinkedLemma); cells.add(currentLinkedLemma); cells.add(currentLink); x = x + width; } private DefaultGraphCell createCell(String name, double x, double y) { DefaultGraphCell cell = new DefaultGraphCell(name); GraphConstants.setBounds(cell.getAttributes(), new Rectangle2D.Double(x, y, width, height)); GraphConstants.setBorder(cell.getAttributes(), BorderFactory.createRaisedBevelBorder()); GraphConstants.setOpaque(cell.getAttributes(), true); GraphConstants.setGradientColor(cell.getAttributes(), Color.LIGHT_GRAY); cell.addPort(new Point2D.Double(0, 0)); return cell; } private DefaultGraphCell createEdge(DefaultGraphCell source, DefaultGraphCell target) { DefaultEdge edge = new DefaultEdge(); source.addPort(); edge.setSource(source.getChildAt(source.getChildCount() -1)); target.addPort(); edge.setTarget(target.getChildAt(target.getChildCount() -1)); GraphConstants.setLabelAlongEdge(edge.getAttributes(), true); GraphConstants.setLineEnd(edge.getAttributes(), GraphConstants.ARROW_CLASSIC); return edge; } Notes about the codeCreating layout in JGraphOne thing JGraph does not offer is a way to automatically create a good layout. For instance, when developing the Wikipedia browser it is necessary to assign x and y coordinates to nodes, otherwise all the cells would be displayed on top of each other. If you create a lot of graphs, or very complex ones, you might want to consider purchasing JGraph Layout Pro , an additional package available from the makers of JGraph. JGraph Layout Pro presents a number of layout algorithms that automatically create usable layouts so that you do not have to assign node coordinates manually. The x and y variables shown in Listing 7 are used to position cells in the graph. Because a Wikipedia lemma can have a large number of links to other lemmata, you will display the linked lemmata in two rows, thus reducing the horizontal screen space required to display the resulting graph. You might notice the edges are not given any coordinates at all. This is not necessary because JGraph is aware of the relationship between the edge and the nodes and will position the edges automatically, based on the positions of the source and the target of the edge.Note that the user object in a cell can be any object. Using Strings is just an easy solution for this exercise. Another thing to note is that every cell has an attribute map that holds name/value pairs. I’ve used the GraphConstants utility class to set these. As you can see, a lot of visualization options are available. The port construct can be regarded as a specific point on the node that the edge connects to. A node can have a number of ports.The last step in creating the graph is to populate the model with the cells that have been created, as shown in Listing 8. Listing 8. Populating the modelgraph.getGraphLayoutCache().insert(cells.toArray()); And that is it — besides the usual Swing stuff that needs to be inserted to actually show a window with content to the user. (See the code archive for the complete application source.) Event handling for user interactionWith just a little more work you will have created a mini Wikipedia browser. You simply need to add a way to allow the user to click on a cell and use that event to determine which lemma the user wants to view next.You do this by adding a MouseListener to the graph. The MouseListener implements the mouseClicked method. When a user clicks on a cell, the browser application will retrieve the data for the lemma the user clicked on, create a new graph, and display it.Listing 9. Adding the MouseListener public void mouseClicked(MouseEvent event) { if (event.getClickCount() == 1) { int x = event.getX(); int y = event.getY(); // Check if a cell is present at the clicked coordinates and return it. DefaultGraphCell cell = (DefaultGraphCell)graph.getSelectionCellAt(new Point2D.Double(x, y)); if (cell != null) { System.out.println(“Next lemma: “ + cell.toString()); } } } Note that the graph object used in the MouseListener implementation is the graph you have been working on so far.Saving the imageJGraph supports exporting graphs as images. The Wikipedia browser application has a Save image button that allows a user to export the current graph as an image. Exporting a graph to an image file is easy, as shown in Listing 10.Listing 10. Exporting a graph to an image file try { BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName)); BufferedImage image = graph.getImage(graph.getBackground(), 10); ImageIO.write(image, "png", out); } catch (Exception e) { // handle exception } Run the Wikipedia browserAll the essential parts of the program are in place. Running it will show something like what you see in Figure 1.Figure 1. A Wikipedia browser display. Click the thumbnail for a larger image.You can run the sample program to further explore what JGraph has to offer. It is easy to rearrange the layout of the graph by dragging the nodes to a new location. JGraph keeps track of the edges and redraws the edge between two nodes if necessary. JGraph supports grouping of cells and allows a user to move a selected number of cells in a single operation.SummaryIn this article you’ve seen one way of using a graph to show only the relevant data in a much larger data set. In this case, you’ve created a simple browser to extract data from the Wikipedia Web site and make it available to users in an easy visual format. There are countless other ways to use graphs to simplify data, including the data used for Java application programming. Consider the following uses for graphs:Display the structure of the web.xml file for a Java Web application. This is especially useful if you want to show which filters will be triggered by a request for a certain URL.Relate logging events recorded in a log file to one another.Show relationships between classes and interfaces in a number of Java source files.The most useful application of graphing to Java development would probably be using graphical editors for application configuration. At the moment a lot of applications use XML-based files to store application configuration data. Some shops then use a Java-XML binding tool like JAXB to create an object tree representing the XML configuration. Using JGraph to visually display that tree would be an improvement on this setup. Being able to change values or even the structure of the data within the visual display (the graph) would make it much easier to change an application’s XML configuration, and the JAXB-generated objects could ensure the changes conformed to the XML Schema describing the configuration data. See the Resources section to learn more about JGraph and download the complete Wikipedia browser created in this article.Jeroen van Bergen started working in information technology in 1993. He has worked in the fields of billing, systems integration, and order management in the telecommunication industry. He has been programming in Java since 2000. Jeroen is at the moment mainly interested in workflow, Java-XML binding, and automatic document generation using Velocity and XSL:FO. Open SourceSoftware DevelopmentWeb DevelopmentJavaDevelopment ToolsTechnology IndustryData Visualization