treeops

TreeOps (Tree Operations)

Build Status

TreeOps is a visual tool for reading, transforming and comparing tree data in different formats. The following formats are supported:

TreeOps defines set of data tree transformations to facilitate typical data manipulations:

Transformations can be saved and re-applied again later.

TreeOps can effortlessly generate Java classes that will read and represent transformed data as simple POJOs(plain old java objects).

User can select paths to be ignored by comparison.

The project is hosted on github

Table of contents

  1. Example: Use Case
  2. Example: Transforming XML to CSV
  3. Example: Comparing
  4. Example: Filtering
  5. Example: Indexing and Regular expressions
  6. Example: Group and append child name
  7. Example: Customizing generated code and inheritance
  8. Structural, value-holder and value nodes
  9. Tree schema information
  10. Transformations
  11. Types tab
  12. Installation
  13. License
  14. Related links

Use case

Third-party data processing is a common requirement in modern software development. Data can be presented as a single file or a collection of files and might come without a detailed description (e.g. XML schema/DTD/JSON schema). Even when the description is provided in some cases the relevant data subset for your project is much more simple than the unfiltered data.

Initial data analysis can be done in TreeOps visual tool based on the samples provided by third-party:

Then you can easily re-apply transformations to the new data received using the generated code or visual tool.

This tasks can be achieved using custom code or XSLT transformations.

Example: Transforming XML to CSV

Suppose we want to convert following XML to CSV:

<root>
    <row rowId="1">
        <column columnId="row1col1">
            <value valId="row1col1val1"/>
            <value valId="row1col1val2"/>
        </column>
        <column columnId="row1col2">
            <value valId="row1col2val1"/>
            <value valId="row1col2val2"/>
        </column>
    </row>
    <row rowId="2">
        <column columnId="row2col1">
            <value valId="row2col1val1"/>
            <value valId="row2col1val2"/>
        </column>
        <column columnId="row2col2">
            <value valId="row2col2val1"/>
            <value valId="row2col2val2"/>
        </column>
    </row>
</root>

We can load XML into the tool using menu File/Load Xml or by using tab Input/Output to type text directly. Please note, that when the folder is selected, all files with relevant extension will be imported recursively.

Enter text into the Text Input textfield and press “Load as XML text” button:

“Table” tab now displays two rows, as the root node have two children. We would like to flatten the tree to display 8 rows in the table.

Example: Comparing

Lets compare two XML trees:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<order>
    <customer name="John"/>
    <item productId="soap" quantity="100"/>
    <item productId="bread" quantity="20"/>
</order>

and

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<order>
    <customer/>
    <item productId="soap" quantity="30"/>
</order>

The result:

Example: Filtering

Filtering transformation removes root’s children that do not have given node. Load the following XML:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<friends>
    <friend age="8" name="Emma" sport="tennis">
        <pet>
            <dog collarType="leather" name="Bear"/>
        </pet>
    </friend>
    <friend age="9" name="Bob" sport="football">
        <pet>
            <dog collarType="chain" name="Bella"/>
        </pet>
    </friend>
    <friend age="10" name="Nick" sport="badminton">
        <pet>
            <cat favouriteCatFood="fish" name="Fluffy"/>
        </pet>
    </friend>
</friends>

We would like to filter out all friends that do not have a dog.

[
    {
        "name": "Emma",
        "sport": "tennis",
        "age": "8",
        "pet": {
            "dog": {
                "collarType": "leather",
                "name": "Bear"
            }
        }
    },
    {
        "name": "Bob",
        "sport": "football",
        "age": "9",
        "pet": {
            "dog": {
                "collarType": "chain",
                "name": "Bella"
            }
        }
    }
]

Example: Indexing and Regular expressions

Indexing transformation adds index within parent as suffix.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
    <element>
        <name>first</name>
    </element>
    <element>
        <name>second</name>
    </element>
</root>

We can use other regular expression transformations to revert Indexing:

Two new nodes have been added

Now lets get rid of index suffix:

Now we have our original tree back after applying number of transformations:

Example: Group and append child name

Suppose we want to group rows in the following XML by the color:

<root>
    <row color="green" id="1"/>
    <row color="green" id="2"/>
    <row color="blue" id="3"/>
</root>

Let’s load this file into the tool using Input panel:

Rows have been grouped by color:

Let’s append color to the Group node name.

Now color have been appended to the Group:

Example: Customizing generated code and inheritance

Suppose we want to read following file into the object model:

<friends>
    <friend age="8" name="Emma" sport="tennis">
        <pet>
            <dog collarType="leather" name="Bear"/>
        </pet>
    </friend>
    <friend age="9" name="Bob" sport="football">
        <pet>
            <dog collarType="chain" name="Bella"/>
        </pet>
    </friend>
    <friend age="10" name="Nick" sport="badminton">
        <pet>
            <cat favouriteCatFood="fish" name="Fluffy"/>
        </pet>
    </friend>
</friends>

Let’s load this file into the tool using Input panel:

We would like to generate Java classes to read this file into the friendly object model.

Double click on path “friends/friend” in the bottom right corner to show “Schema” tab again. Now we would like to introduce Animal type for “cat” and “dog” to inherit from.


public class Friends {
	private List<Friend> friend = new ArrayList<>();
}

public class Friend {
	private String name;
	private Sport sport;
	private Integer age;
	private Pet pet;
}

public class Pet {
	private Animal animal;
}

public class Animal {
	private String name;
}	

public class Cat extends Animal {
	private String favouriteCatFood;
}

public class Dog extends Animal {
	private String collarType;
}	

public enum Sport {
	BADMINTON("badminton"), FOOTBALL("football"), TENNIS("tennis");
}

public class Reader {
	public static void main(String[] args) throws Exception {
		Friends res = readFriends(readXml(new File(args[0])));
	}
	public static DataNode readJson(File file) throws Exception {
		return Transformation.runAll(readTransformations(), JsonReader.read(file));
	}
	public static DataNode readXml(File file) throws Exception {
		return Transformation.runAll(readTransformations(), XmlReader.read(file));
	}
	public static DataNode readCsv(File file) throws Exception {
		return Transformation.runAll(readTransformations(), CsvReader.read(file));
	}
	public static Friends readFriends(DataNode n) {
		Friends o = new Friends();
		for (DataNode c : DataNode.children(n)) {
			if ("friend".equals(c.getName())) {
				o.getFriend().add(readFriend(c));
			}
		}
		return o;
	}
	

Structural, value-holder and value nodes

Nodes in the input tree are divided into value-holder nodes, value nodes and structural nodes. Value-holder nodes can have up to one leaf child which holds its value.
Value nodes don’t have children. For example in the tree below:

Tree schema information

The tool displays following schema information for each unique path (excluding value nodes) in the input tree:

Transformations

All transformations take at least one parameter - selected node.

Types tab

“Types” tab displays all types found in a tree. Nodes with the same name are considered to be of the same type. When type is selected, type’s variables and paths are displayed. You can navigate to the relevant schema node by double-clicking on the path.

Installation

TreeOps is built in Java Swing. In order to start visual tool, type:

gradlew run

or build the project and use java -jar option:

gradlew build
java -jar TreeOps.jar

License

Copyright (c) 2006-2017 TreeOps.org

Licensed under the Apache Licence v2