Overview

The Marshaller takes an object in memory and all its references (and their references and so on) and marshals it into a FreeMind mindmap representation in memory. This representation can then be further manipulated and saved to disk. Self-referential structures (such as LinkedList instances) are supported. The first time an object is encountered, a node in the map is created for it and all its children. Subsequent times, a graphical link is drawn to the existing object. The Marshaller is especially handy for comparing the results of methods over time (or over different input values) or for comparing return values between people separated geographically.

FreeMind is an open source tool for visualizing mind maps. The use of FreeMind as an output format allows for large nodes to be automatically closed when the mind map is viewed. The user then never gets lost in detail.

Getting Started

The JavaDoc is available here.

The following examples have source code together with the resulting mindmap:

Example Code

The following code is taken from the MarshallerTest TestCase. Some of the more notable or interesting mindmaps have a link to the source code for that test with the generated mindmap presented as a FreeMind Java applet. You will need at least JRE or JDK version 1.4 for them to work correctly.
package ca.quine.jcommons.marshaller.test;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;

import ca.quine.jcommons.freemind.maputil.MapUtils;
import ca.quine.jcommons.freemind.xml.Map;
import ca.quine.jcommons.freemind.xml.Node;
import ca.quine.jcommons.marshaller.Marshaller;
import junit.framework.TestCase;

public class MarshallerTest extends TestCase {

        /**
         * Test the <code>fqcn</code> method on <code>Marshaller</code>.
         * 
         * @throws Exception
         */
        public void testFqcn() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_ALWAYS, Marshaller.SHOW_ACTUAL_TYPE);

                Map map = marshaller.marshal("Foo");
                assertEquals("java.lang.String", map.getNode().getTEXT());

                marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);
                map = marshaller.marshal("Foo");
                assertEquals("String", map.getNode().getTEXT());
        }

        /**
         * Test <code>String</code> marshalling.
         * 
         * @throws Exception
         */
        public void testString() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_ALWAYS, Marshaller.SHOW_ACTUAL_TYPE);

                Map map = marshaller.marshal("Foo");

                Node node = MapUtils.getRightNode(map);
                assertEquals("Foo", node.getTEXT());
        }

        /**
         * Ensures that an Integer is marshalled with the type "Integer", and an
         * int is marshalled with the type "int".
         * 
         * @throws Exception
         */
        public void testIntegerVsIntType() throws Exception {
                Object object = new Object() {
                        private Integer one = new Integer(1);
                        private int two = 2;

                        /**
                         * Actually use the fields so that Eclipse doesn't give us a
                         * warning.
                         */
                        public String toString() {
                                return "Object:  " + one + ", " + two;
                        }
                };

                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                Map map = marshaller.marshal(object);

                // Check the first Node to the right of the root node.
                Node node = MapUtils.getRightNode(map, 1);
                assertEquals("private Integer one", node.getTEXT());

                // Node 2 is a reference to the outer class (i.e. "this")
                // since the fields are sorted by name.

                // Check the third Node to the right of the root node.
                node = MapUtils.getRightNode(map, 3);
                assertEquals("private int two", node.getTEXT());
        }

        /**
         * Ensures the ArrayList marshaller can request default marshalling of
         * each object in the ArrayList (in this case, they are
         * <code>String</code>s).
         * 
         * @throws Exception
         */
        public void testArrayList() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                ArrayList list = new ArrayList();
                list.add("one");
                list.add("two");
                list.add("three");
                Map map = marshaller.marshal(list);

                Node node = MapUtils.getRightNode(map);
                assertEquals("one", node.getTEXT());
                node = MapUtils.getRightNode(map, 2);
                assertEquals("two", node.getTEXT());
                node = MapUtils.getRightNode(map, 3);
                assertEquals("three", node.getTEXT());
        }

        /**
         * Mostly this test ensures that an infinite loop of some kind doesn't
         * occur, since many of the Objects held by a LinkedList point to internal
         * structures held by it.
         * 
         * @throws Exception
         */
        public void testLinkedList() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                LinkedList list = new LinkedList();
                list.add("one");
                list.add("two");
                list.add("three");
                Map map = marshaller.marshal(list);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\linked-list.mm"));
                map.marshal(bw);
                bw.close();
        }

View the mind map for the linked list

        /**
         * Tests that a <code>HashMap</code> is correctly marshalled.
         * 
         * @throws Exception
         */
        public void testHashMap() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                HashMap hashMap = new HashMap();
                hashMap.put("a", "one");
                hashMap.put("b", "two");
                hashMap.put("c", "three");
                Map map = marshaller.marshal(hashMap);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\hashmap.mm"));
                map.marshal(bw);
                bw.close();
        }

        public void testHashMapOfClasses() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                HashMap hashMap = new HashMap();
                hashMap.put(String.class, "String");
                hashMap.put(Integer.class, "Integer");
                hashMap.put(Long.class, "Long");
                Map map = marshaller.marshal(hashMap);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\hashmap-of-classes.mm"));
                map.marshal(bw);
                bw.close();
        }

View the mind map for the HashMap of classes.

        public void testCharArray() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                char[] object = "abc".toCharArray();
                Map map = marshaller.marshal(object);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\char-array.mm"));
                map.marshal(bw);
                bw.close();
        }

        public void test2DCharArray() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                char[] object1 = "abc".toCharArray();
                char[] object2 = "def".toCharArray();
                char[] object3 = "ghi".toCharArray();
                char[][] object = { object1, object2, object3 };
                Map map = marshaller.marshal(object);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\2d-char-array.mm"));
                map.marshal(bw);
                bw.close();
        }

        public void test3DCharArray() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                char[] object11 = "abc".toCharArray();
                char[] object21 = "def".toCharArray();
                char[] object31 = "ghi".toCharArray();
                char[][] object1 = { object11, object21, object31 };

                char[] object12 = "abc".toCharArray();
                char[] object22 = "def".toCharArray();
                char[] object32 = "ghi".toCharArray();
                char[][] object2 = { object12, object22, object32 };

                char[][][] object = { object1, object2 };

                Map map = marshaller.marshal(object);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\3d-char-array.mm"));
                map.marshal(bw);
                bw.close();
        }

View the mind map for the 3D char array.

        public void testIntArray() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                int[] object = { 1, 2, 3 };
                Map map = marshaller.marshal(object);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\int-array.mm"));
                map.marshal(bw);
                bw.close();
        }

        public void test2DIntArray() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                int[][] object = { {1, 2}, {3, 4}, {5, 6} };
                Map map = marshaller.marshal(object);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\2d-int-array.mm"));
                map.marshal(bw);
                bw.close();
        }

        public void test3DIntArray() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                int[][] object1 = { {1, 2}, {3, 4}, {5, 6} };
                int[][] object2 = { {7, 8}, {9, 10}, {11, 12} };
                int[][][] object = { object1, object2 };
                Map map = marshaller.marshal(object);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\3d-int-array.mm"));
                map.marshal(bw);
                bw.close();
        }

        public void test4DIntArray() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                int[][] object11 = { {1, 2}, {3, 4}, {5, 6} };
                int[][] object21 = { {7, 8}, {9, 10}, {11, 12} };
                int[][][] object1 = { object11, object21 };

                int[][] object12 = { {1, 2}, {3, 4}, {5, 6} };
                int[][] object22 = { {7, 8}, {9, 10}, {11, 12} };
                int[][][] object2 = { object12, object22 };

                int[][][][] object = { object1, object2 };
                Map map = marshaller.marshal(object);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\4d-int-array.mm"));
                map.marshal(bw);
                bw.close();
        }

View the mind map for the 4D int array.

        public void test2DShortArray() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                short[][] object = { {1, 2}, {3, 4}, {5, 6} };
                Map map = marshaller.marshal(object);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\2d-short-array.mm"));
                map.marshal(bw);
                bw.close();
        }

        public void test2DBooleanArray() throws Exception {
                Marshaller marshaller = new Marshaller(
                                Marshaller.FQCN_NEVER, Marshaller.SHOW_ACTUAL_TYPE);

                boolean[][] object = { {true, false}, {true, false}, {true, false} };
                Map map = marshaller.marshal(object);

                BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\temp\\2d-boolean-array.mm"));
                map.marshal(bw);
                bw.close();
        }

}