Fork me on GitHub

Tutorial 11

E11 Using XPath to split the input data

In this tutorial we will render a mindmap as formatted characters. Our algotithm will need the input data split into left and right sides. The task of splitting the mindmap will be done by the projection.


public interface MindMap {
    public interface Node {
        Node[] getSubNodes();
        String getText();
    Node getRootNode();
    Node[] getLeftNodes();
    Node[] getRightNodes();
    int getNodeCount();

Example Code

This is the complete code as JUnit testcase.

public class TestDumpMindMap {
    private static final Comparator<? super String> STRING_LENGTH_COMPARATOR = new Comparator<String>() {
        public int compare(String o1, String o2) {
            return Integer.valueOf(o1.length()).compareTo(o2.length());
    public void dump() throws IOException {
        MindMap mindMap = new XBProjector().io().fromURLAnnotation(MindMap.class);
        List<String> leftLines = new LinkedList<String>();
        List<String> rightLines= new LinkedList<String>();
        walkNodes("", mindMap.getLeftNodes(), leftLines,true);       
        int maxLength = Collections.max(leftLines, STRING_LENGTH_COMPARATOR).length();
        String rootText = mindMap.getRootNode().getText();
        System.out.println(String.format("%1$-" + maxLength + "s", "")+rootText);
        String midSpace=rootText.replaceAll(".", " ");
        for (String s : leftLines) {
            String right=rightLines.isEmpty()?"":rightLines.get(0);
            if (!rightLines.isEmpty()){rightLines.remove(0);};
            String line = reverse(String.format("%1$-" + maxLength + "s", s))+midSpace+right;
        for (String s:rightLines) {
            String line=String.format("%1$-" + maxLength + "s", "")+midSpace+s;
    private void walkNodes(String prefix, Node[] leftNodes, List<String> lines,boolean reverse) {
        for (Node n : leftNodes) {
            lines.add((prefix + (reverse ?  reverse(n.getText()) : n.getText()) ));
            walkNodes(prefix + (n.getText()).replaceAll(".", " "), n.getSubNodes(), lines,reverse);
    private String reverse(final String s) {
        return new StringBuffer(s).reverse().toString();

Test Output

                                           Projector       Metadata
                              Configuration                        Definition
                     Factories                                               @XBead
               Parser                                                              XPath
     Document Builder                                                              TargetComponentType
                XPath                                                        @XBWrite
must be serializeable                                                                Limited XPath
           NamespacePhilosophy                                               @XBDelete
                              Instantiation                                  Parameterizing
                                          Projection               Externalization
                          Projection Types                                        Properties
      Projection Interface                                                                  By package.class.method
             Subprojection                                                                  By class.method
      External Projections                                                                  By method
         Projection Method                                                                  By Key
                                 Instances                                        Custom
                    Instantiation                                                       must be serializeable
            "Virtual Projections"                          IO
                        POJO like                            Input
       Equals & HashCode                                          String
           Serialization                                          File
                  Mixins                                          Stream
             Inheritance                                          URL
                                           DataTypes                 HTTP GET
                                 Converting                                  Request Customization
                      CustomTypes                                                                 Document
                                Collections                                                       ExternalDocumentProjection
                                 Primitives                          Resource
                             Subprojections                  Output
                                          DOM Access               Document Building
                       Projection Document                                          PrettyPrinting
                        Projection Element                                          XML Header control
                            Simple Casting                                          Encoding
                     interface inheritance                         asString()
    DOM is backend, can be changed anytime                         File
                                                                      HTTP POST