Overview

MapUtils provides a set of convenience methods that can be used to create, write (marshal), read (unmarshal) and manipulate FreeMind mindmaps. Auto-generated Castor objects are the basis for this implementation. MapUtils includes the following features:

  • folding nodes that contain more than a given number of child nodes
  • unfolding all nodes in a given map
  • convenience methods for creating nodes with given text and adding a child node to a parent node
  • various searches for nodes with provided text (including regular expressions)
  • executing a provided "apply" method for all nodes in a map in 4 different traversal orders (including BFS and DFS)

JavaDoc

The JavaDoc is available here. Also specifically look at the MapUtils Utility class and the ApplicatorTests test case.

Getting Started

The following code is from the TestCase MapUtilsTest. It shows several useful features of MapUtils.
package ca.quine.jcommons.freemind.maputil.test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;

import org.exolab.castor.xml.XMLException;

import ca.quine.jcommons.freemind.maputil.MapUtils;
import ca.quine.jcommons.freemind.maputil.NodeComparator;
import ca.quine.jcommons.freemind.maputil.NodeItemComparator;
import ca.quine.jcommons.freemind.maputil.SearchNodeApplicator;
import ca.quine.jcommons.freemind.xml.Map;
import ca.quine.jcommons.freemind.xml.Node;
import ca.quine.jcommons.freemind.xml.types.NodeItemFOLDEDType;
import ca.quine.jcommons.freemind.xml.types.NodeItemPOSITIONType;
import junit.framework.TestCase;

/**
 * Code samples/test cases for the <code>MapUtils</code> Utility class.
 * To run these, castor-1.0.3.jar, commons-logging-1.1.jar and
 * xerces.jar (or xercesImpl.jar) are required on the classpath.
 * See http://jcommons.sourceforge.net/ for download links.
 */
public class MapUtilsTest extends TestCase {

        /**
         * Creates a mindmap with sample data, marshals it to a file,
         * unmarshals it, and verifies the data is correct.
         * 
         * @throws IOException
         * @throws XMLException
         */
        public void testMindMapMarshalAsFile() throws IOException, XMLException
        {
                Node rootNode = MapUtils.makeNode("root");

                Map map = new Map();
                map.setVersion("0.8.0");
                map.setNode(rootNode);

                Node rightChild1 = MapUtils.makeNode("right child 1");
                Node rightChild2 = MapUtils.makeNode("right child 2");
                Node leftChild1 = MapUtils.makeNode("left child 1",
                                NodeItemPOSITIONType.LEFT);
                Node leftChild2 = MapUtils.makeNode("left child 2",
                                NodeItemPOSITIONType.LEFT);

                MapUtils.addChild(rootNode, rightChild1);
                MapUtils.addChild(rootNode, rightChild2);
                MapUtils.addChild(rootNode, leftChild1);
                MapUtils.addChild(rootNode, leftChild2);

                // Write (marshal) the Map as a FreeMind mindmap file.
                BufferedWriter bw = new BufferedWriter(
                                new FileWriter("c:\\temp\\sample-map.mm"));
                map.marshal(bw);
                bw.close();

                // Read (unmarshal) the Map we just wrote.
                BufferedReader br = new BufferedReader(
                                new FileReader("c:\\temp\\sample-map.mm"));
                Map newMap = Map.unmarshal(br);

                assertEquals("left child 1", MapUtils.getLeftNode(newMap, 1).getTEXT());
                assertEquals("left child 2", MapUtils.getLeftNode(newMap, 2).getTEXT());
                assertEquals("right child 1", MapUtils.getRightNode(newMap, 1).getTEXT());
                assertEquals("right child 2", MapUtils.getRightNode(newMap, 2).getTEXT());
        }

        public void testMakeNodeAndGetNode() {
                Node rootNode = MapUtils.makeNode("root");

                Map map = new Map();
                map.setNode(rootNode);

                Node rightChild1 = MapUtils.makeNode("right child 1");
                Node rightChild2 = MapUtils.makeNode("right child 2");
                Node leftChild1 = MapUtils.makeNode("left child 1",
                                NodeItemPOSITIONType.LEFT);
                Node leftChild2 = MapUtils.makeNode("left child 2",
                                NodeItemPOSITIONType.LEFT);

                // Insert the Nodes interleaved, and make sure we can access them in
                // the right order.
                MapUtils.addChild(rootNode, rightChild1);
                MapUtils.addChild(rootNode, leftChild1);
                MapUtils.addChild(rootNode, rightChild2);
                MapUtils.addChild(rootNode, leftChild2);

                assertEquals(rightChild1, MapUtils.getRightNode(map));
                assertEquals(rightChild1, MapUtils.getRightNode(map, 1));
                assertEquals(rightChild2, MapUtils.getRightNode(map, 2));

                assertEquals(leftChild1, MapUtils.getLeftNode(map));
                assertEquals(leftChild1, MapUtils.getLeftNode(map, 1));
                assertEquals(leftChild2, MapUtils.getLeftNode(map, 2));
        }

        public void testCountAndCloseLargeNodes() {
                Node rootNode = MapUtils.makeNode("root");

                Map map = new Map();
                map.setNode(rootNode);

                Node child1 = MapUtils.makeNode("one");
                Node child2 = MapUtils.makeNode("two");
                MapUtils.addChild(rootNode, child1);
                MapUtils.addChild(rootNode, child2);

                MapUtils.addChild(child1, MapUtils.makeNode("three"));
                MapUtils.addChild(child1, MapUtils.makeNode("four"));
                MapUtils.addChild(child1, MapUtils.makeNode("five"));

                MapUtils.closeLargeNodes(map, 2);

                assertEquals(null, rootNode.getFOLDED());
                assertEquals(NodeItemFOLDEDType.TRUE, child1.getFOLDED());
                assertEquals(null, child2.getFOLDED());
        }

        public void testSortMap() {
                Node rootNode = MapUtils.makeNode("root");

                Map map = new Map();
                map.setNode(rootNode);

                Node nodeA = MapUtils.makeNode("a");
                MapUtils.addChild(rootNode, nodeA);
                MapUtils.addChild(rootNode, MapUtils.makeNode("c"));
                MapUtils.addChild(rootNode, MapUtils.makeNode("b"));

                MapUtils.addChild(nodeA, MapUtils.makeNode("a"));
                MapUtils.addChild(nodeA, MapUtils.makeNode("c"));
                MapUtils.addChild(nodeA, MapUtils.makeNode("b"));

                MapUtils.sortMap(map);

                assertEquals("a", MapUtils.getRightNode(map, 1).getTEXT());
                assertEquals("b", MapUtils.getRightNode(map, 2).getTEXT());
                assertEquals("c", MapUtils.getRightNode(map, 3).getTEXT());

                assertEquals("a", MapUtils.getChild(nodeA, 1).getTEXT());
                assertEquals("b", MapUtils.getChild(nodeA, 2).getTEXT());
                assertEquals("c", MapUtils.getChild(nodeA, 3).getTEXT());
        }

        public void testSortMapWithNodeComparator() {
                Node rootNode = MapUtils.makeNode("root");

                Map map = new Map();
                map.setNode(rootNode);

                MapUtils.addChild(rootNode, MapUtils.makeNode("103"));
                MapUtils.addChild(rootNode, MapUtils.makeNode("1"));
                MapUtils.addChild(rootNode, MapUtils.makeNode("2"));

                // Sort with regular lexical ordering.
                MapUtils.sortMap(map);

                assertEquals("1", MapUtils.getRightNode(map, 1).getTEXT());
                assertEquals("103", MapUtils.getRightNode(map, 2).getTEXT());
                assertEquals("2", MapUtils.getRightNode(map, 3).getTEXT());

                NodeItemComparator comparator = new NodeItemComparator(
                        new NodeComparator() {
                                public int compare(Node node1, Node node2) {
                                        return (new Integer(node1.getTEXT()).compareTo(
                                                        new Integer(node2.getTEXT())));
                                }
                        }
                );

                // Sort with numerical ordering.
                MapUtils.sortMap(map, comparator);

                assertEquals("1", MapUtils.getRightNode(map, 1).getTEXT());
                assertEquals("2", MapUtils.getRightNode(map, 2).getTEXT());
                assertEquals("103", MapUtils.getRightNode(map, 3).getTEXT());
        }

        public void testSortNode() {
                Node rootNode = MapUtils.makeNode("root");

                MapUtils.addChild(rootNode, MapUtils.makeNode("a"));
                MapUtils.addChild(rootNode, MapUtils.makeNode("c"));
                MapUtils.addChild(rootNode, MapUtils.makeNode("b"));

                MapUtils.sortNode(rootNode);

                assertEquals("a", MapUtils.getChild(rootNode, 1).getTEXT());
                assertEquals("b", MapUtils.getChild(rootNode, 2).getTEXT());
                assertEquals("c", MapUtils.getChild(rootNode, 3).getTEXT());
        }

        public void testSortNodeWithNodeComparator() {
                Node rootNode = MapUtils.makeNode("root");

                MapUtils.addChild(rootNode, MapUtils.makeNode("103"));
                MapUtils.addChild(rootNode, MapUtils.makeNode("1"));
                MapUtils.addChild(rootNode, MapUtils.makeNode("2"));

                // Sort with regular lexical ordering.
                MapUtils.sortNode(rootNode);

                assertEquals("1", MapUtils.getChild(rootNode, 1).getTEXT());
                assertEquals("103", MapUtils.getChild(rootNode, 2).getTEXT());
                assertEquals("2", MapUtils.getChild(rootNode, 3).getTEXT());

                NodeItemComparator comparator = new NodeItemComparator(
                        new NodeComparator() {
                                public int compare(Node node1, Node node2) {
                                        return (new Integer(node1.getTEXT()).compareTo(
                                                        new Integer(node2.getTEXT())));
                                }
                        }
                );

                // Sort with numerical ordering.
                MapUtils.sortNode(rootNode, comparator);

                assertEquals("1", MapUtils.getChild(rootNode, 1).getTEXT());
                assertEquals("2", MapUtils.getChild(rootNode, 2).getTEXT());
                assertEquals("103", MapUtils.getChild(rootNode, 3).getTEXT());
        }

        /**
         * Ensure that a DFS pre-order traversal happens in the right order.
         */
        public void testApplyDFSPreOrder() {
                Node[] nodeArray = new Node[7];
                for (int i = 0; i < nodeArray.length; i++) {
                        nodeArray[i] = MapUtils.makeNode("" + i);
                }

                Map map = new Map();
                map.setNode(nodeArray[0]);


// Depth first search, pre-order traversal:
//
//       2
//      /
//     1
//    / \
//   /   3
//  0
//   \   5
//    \ /
//     4
//      \
//       6
                MapUtils.addChild(nodeArray[0], nodeArray[1]);
                MapUtils.addChild(nodeArray[0], nodeArray[4]);
                MapUtils.addChild(nodeArray[1], nodeArray[2]);
                MapUtils.addChild(nodeArray[1], nodeArray[3]);
                MapUtils.addChild(nodeArray[4], nodeArray[5]);
                MapUtils.addChild(nodeArray[4], nodeArray[6]);

                SearchNodeApplicator applicator = new SearchNodeApplicator(
                                SearchNodeApplicator.SEARCH_CONTAINS, "");

                MapUtils.apply(map, MapUtils.TRAVERSAL_DFS_PREORDER, applicator);

                verifyOrder(applicator.getMatchedNodes());
        }

        /**
         * Ensure that a DFS post-order traversal happens in the right order.
         */
        public void testApplyDFSPostOrder() {
                Node[] nodeArray = new Node[7];
                for (int i = 0; i < nodeArray.length; i++) {
                        nodeArray[i] = MapUtils.makeNode("" + i);
                }

                Map map = new Map();
                map.setNode(nodeArray[0]);

// Depth first search, post-order traversal:
//
//       0
//      /
//     2
//    / \
//   /   1
//  6
//   \   3
//    \ /
//     5
//      \
//       4
                MapUtils.addChild(nodeArray[2], nodeArray[0]);
                MapUtils.addChild(nodeArray[2], nodeArray[1]);
                MapUtils.addChild(nodeArray[5], nodeArray[3]);
                MapUtils.addChild(nodeArray[5], nodeArray[4]);
                MapUtils.addChild(nodeArray[6], nodeArray[2]);
                MapUtils.addChild(nodeArray[6], nodeArray[5]);

                SearchNodeApplicator applicator = new SearchNodeApplicator(
                                SearchNodeApplicator.SEARCH_CONTAINS, "");

                MapUtils.apply(map, MapUtils.TRAVERSAL_DFS_POSTORDER, applicator);

                verifyOrder(applicator.getMatchedNodes());
        }

        /**
         * Ensure that a BFS traversal happens in the right order.
         */
        public void testApplyBFS() {
                Node[] nodeArray = new Node[7];
                for (int i = 0; i < nodeArray.length; i++) {
                        nodeArray[i] = MapUtils.makeNode("" + i);
                }

                Map map = new Map();
                map.setNode(nodeArray[0]);

// Depth first search, post-order traversal:
//
//       3
//      /
//     1
//    / \
//   /   4
//  0
//   \   5
//    \ /
//     2
//      \
//       6
                MapUtils.addChild(nodeArray[0], nodeArray[1]);
                MapUtils.addChild(nodeArray[0], nodeArray[2]);
                MapUtils.addChild(nodeArray[1], nodeArray[3]);
                MapUtils.addChild(nodeArray[1], nodeArray[4]);
                MapUtils.addChild(nodeArray[2], nodeArray[5]);
                MapUtils.addChild(nodeArray[2], nodeArray[6]);

                SearchNodeApplicator applicator = new SearchNodeApplicator(
                                SearchNodeApplicator.SEARCH_CONTAINS, "");

                MapUtils.apply(map, MapUtils.TRAVERSAL_BFS, applicator);

                verifyOrder(applicator.getMatchedNodes());
        }

        public void testSearchContains() {
                Node[] nodeArray = new Node[7];
                for (int i = 0; i < nodeArray.length; i++) {
                        nodeArray[i] = MapUtils.makeNode("" + i);
                }

                Map map = new Map();
                map.setNode(nodeArray[0]);

                MapUtils.addChild(nodeArray[0], nodeArray[6]);
                MapUtils.addChild(nodeArray[6], nodeArray[2]);
                MapUtils.addChild(nodeArray[6], nodeArray[5]);
                MapUtils.addChild(nodeArray[2], nodeArray[1]);
                MapUtils.addChild(nodeArray[5], nodeArray[3]);
                MapUtils.addChild(nodeArray[5], nodeArray[4]);

                // Return all the nodes in order by searching for them.
                ArrayList matchedNodes = MapUtils.search(map,
                                SearchNodeApplicator.SEARCH_CONTAINS, "3");

                assertEquals(1, matchedNodes.size());
                assertEquals("3", ((Node) matchedNodes.get(0)).getTEXT());
        }

        public void testSearchExactMatch() {
                Node[] nodeArray = new Node[7];
                for (int i = 0; i < nodeArray.length; i++) {
                        nodeArray[i] = MapUtils.makeNode("" + i);
                }

                Map map = new Map();
                map.setNode(nodeArray[0]);

                MapUtils.addChild(nodeArray[0], nodeArray[6]);
                MapUtils.addChild(nodeArray[6], nodeArray[2]);
                MapUtils.addChild(nodeArray[6], nodeArray[5]);
                MapUtils.addChild(nodeArray[2], nodeArray[1]);
                MapUtils.addChild(nodeArray[5], nodeArray[3]);
                MapUtils.addChild(nodeArray[5], nodeArray[4]);

                // Return all the nodes in order by searching for them.
                ArrayList matchedNodes = MapUtils.search(map,
                                SearchNodeApplicator.SEARCH_EXACT_MATCH, "3");

                assertEquals(1, matchedNodes.size());
                assertEquals("3", ((Node) matchedNodes.get(0)).getTEXT());
        }

        public void testSearchRegex() {
                Node[] nodeArray = new Node[7];
                for (int i = 0; i < nodeArray.length; i++) {
                        nodeArray[i] = MapUtils.makeNode("" + i);
                }

                Map map = new Map();
                map.setNode(nodeArray[0]);

                MapUtils.addChild(nodeArray[0], nodeArray[6]);
                MapUtils.addChild(nodeArray[6], nodeArray[2]);
                MapUtils.addChild(nodeArray[6], nodeArray[5]);
                MapUtils.addChild(nodeArray[2], nodeArray[1]);
                MapUtils.addChild(nodeArray[5], nodeArray[3]);
                MapUtils.addChild(nodeArray[5], nodeArray[4]);

                // Return all the nodes that match the regex "[0-3]".
                ArrayList matchedNodes = MapUtils.search(map,
                                SearchNodeApplicator.SEARCH_REGEXP, "[0-3]");

                assertEquals(4, matchedNodes.size());

                // Make sure all 4 nodes are different.
                HashSet set = new HashSet();
                Iterator iter = matchedNodes.iterator();
                while (iter.hasNext()) {
                        Node node = (Node) iter.next();
                        set.add(node);
                }

                // If any of the nodes are the same, then the set will not have 4
                // elements.
                assertEquals(4, set.size());
        }

        private void verifyOrder(ArrayList nodeList) {
                for (int i = 0; i < nodeList.size(); i++) {
                        Node node = (Node) nodeList.get(i);
                        assertEquals(i, Integer.parseInt(node.getTEXT()));
                }
        }

}