Difference between revisions of "The Tree Library"
m (moved The Trees Library to The Tree Library) |
|||
Line 1: | Line 1: | ||
+ | The '''Tree Library''' implements a model of ''edge-labelled trees'', and related tools. It is a shared dependency for the components of a subsystem that provides data access under this model, including the Tree Manager services, the [[The Tree Manager Framework|Tree Manager Framework]], the [[The Tree Manager Library|Tree Manager Library]] and its clients. | ||
− | + | The library is available in our Maven repositories with the following coordinates: | |
+ | |||
+ | <source lang="java5"> | ||
+ | |||
+ | <groupId>org.gcube.data.access</groupId> | ||
+ | <artifactId>trees</artifactId> | ||
+ | <version>...</version> | ||
+ | |||
+ | </source> | ||
+ | |||
+ | Sources and documentation are also available in the repositories as secondary artefacts with classifiers <code>sources</code> and <code>javadoc</code>, respectively: | ||
+ | |||
+ | <source lang="java5"> | ||
+ | |||
+ | <groupId>org.gcube.data.access</groupId> | ||
+ | <artifactId>trees</artifactId> | ||
+ | <classifier>sources</code> | ||
+ | <version>...</version> | ||
+ | |||
+ | <groupId>org.gcube.data.access</groupId> | ||
+ | <artifactId>trees</artifactId> | ||
+ | <classifier>javadoc</code> | ||
+ | <version>...</version> | ||
+ | |||
+ | </source> | ||
+ | |||
+ | |||
+ | = Trees = | ||
+ | |||
+ | The library implements a model of ''node-attributed'', ''leaf-valued'' , ''edge-labelled'', and ''directed trees''. In particular: | ||
+ | |||
+ | * nodes may have an identifier and a number of uniquely named attributes; | ||
+ | * edges have a label; | ||
+ | * leaves may have a value; | ||
+ | * roots may identify the source of origin. | ||
+ | |||
+ | Moreover: | ||
+ | |||
+ | * identifiers, attributes, and leaves have text values; | ||
+ | * attribute names and labels may be namespaced. | ||
+ | |||
+ | |||
+ | [[Image:tree-model.png|center]] | ||
+ | |||
+ | |||
+ | The model is implemented in code by the following classes: | ||
+ | |||
+ | [[Image:tree-class-hierarchy.png|center]] | ||
+ | |||
+ | Nodes are either <code>InnerNode</code>s or <code>Leaf</code>s. <code>InnerNode</code>s have zero or more <code>Edge</code>s, each of which has a label and target <code>Node</code>. Attributes and identifiers are common to all <code>Node</code>s, while only <code>Leaf</code>s have values. <code>Tree</code>s are <code>InnerNode</code>s with source identifiers, and serve as tree roots. | ||
+ | |||
+ | Instances of ''model classes'' are mutable, in that we can: | ||
+ | |||
+ | * add and remove attributes and edges; | ||
+ | * change the value of attributes and leaves; | ||
+ | * change source identifiers; | ||
+ | |||
+ | Note however that node identifiers and edge labels are assigned at creation time and cannot be changed thereafter. | ||
+ | |||
+ | We can also: | ||
+ | |||
+ | * compare instances for equivalence (instances override <code>equals()</code>); | ||
+ | * use them as keys in hash-based structures (instances override <code>hashcode()</code>); | ||
+ | * publish their state for debugging purposes (instances override <code>toString()</code>). | ||
+ | |||
+ | ==Building Trees== | ||
+ | |||
+ | We can construct trees in a standard object-oriented fashion, using any of the overloaded constructors common to all model classes (including ''copy constructors''), e.g: | ||
+ | |||
+ | <source lang="java5"> | ||
+ | |||
+ | Tree tree = new Tree("rootId"); | ||
+ | tree.setAttribute(new QName("x"),"1"); | ||
+ | tree.setAttribute(new QName("http://foo.org","y"), new Date().toString()); | ||
+ | tree.setSourceID("sourceId"); | ||
+ | Leaf leaf1 = new Leaf("id1"); | ||
+ | leaf1.value("1"); | ||
+ | Leaf leaf2 = new Leaf("id2"); | ||
+ | leaf2.value("true"); | ||
+ | Edge e1 = new Edge(new QName("a"),leaf1); //unqualified | ||
+ | Edge e2 = new Edge(new QName("http://bar.org","b"),leaf2); | ||
+ | tree.add(e1,e2) | ||
+ | </source> | ||
+ | |||
+ | Overloaded constructors simplify object creation, e.g.: | ||
+ | |||
+ | <source lang="java5"> | ||
+ | Tree tree = new Tree("rootId", | ||
+ | new Edge("a", new Leaf("id1","2")), | ||
+ | new Edge("http://bar.org","b", new Leaf("id2","true"))); | ||
+ | |||
+ | tree.setAttribute("x","1"); | ||
+ | tree.setAttribute("http://foo.org","y", new Date().toString()); | ||
+ | tree.setSourceID("sourceId"); | ||
+ | |||
+ | </source> | ||
+ | |||
+ | We find details on individual constructor and mutators in the in Javadoc documentation. | ||
+ | |||
+ | Alternatively, we can adopt a more functional style importing the static builder methods of the <code>Nodes</code> class and composing them in tree expressions, e.g: | ||
+ | |||
+ | <source lang="java5"> | ||
+ | |||
+ | import static org.gcube.data.trees.data.Nodes.*; | ||
+ | … | ||
+ | Tree tree = attr(t("sourceId","rootId", | ||
+ | e("a",1), | ||
+ | e("http://bar.org","b",true)), | ||
+ | a("x",1),a("http://foo.org","y",new Date())); | ||
+ | |||
+ | </source> | ||
+ | |||
+ | The functional style is far less verbose, and is particularly suited for testing. <code>t()</code>, <code>attr()</code>, <code>e()</code>, and <code>a()</code> are examples of root, attribute, and edge builders, respectively. We use them to inline tree expressions, i.e. avoid the <code>new</code> operator for <code>Node</code>s, <code>Edge</code>s and <code>QName</code>s. They also perform object-to-string conversion (cf. <code>int</code>, <code>boolean</code>, and <code>Date</code> above). | ||
+ | |||
+ | We find details on all the available builders in the Javadoc documentation of the Nodes class. See also these additional examples: | ||
+ | |||
+ | <source lang="java5"> | ||
+ | |||
+ | // n() is an inner node generator | ||
+ | Tree tree = t("rootId", | ||
+ | e("a", n("2", | ||
+ | e("b",3)))); | ||
+ | |||
+ | |||
+ | tree = t( | ||
+ | e("a", attr( | ||
+ | n("2", | ||
+ | e("b",l("3",0)), //l()= explicit leaf generator for identity assignment | ||
+ | e("a",l("4",0))), | ||
+ | a("foo","0")))); | ||
+ | |||
+ | |||
+ | tree = attr(t("1", | ||
+ | e("a",l("2",5)), | ||
+ | e("b",attr( | ||
+ | n("3",e("c",4)), | ||
+ | a("foo",0))), | ||
+ | e("c",5)), | ||
+ | a("x",0)); | ||
+ | |||
+ | |||
+ | tree = attr(t("1", | ||
+ | e("a", n("2", | ||
+ | e("b",n("$2")))), | ||
+ | e("a",n("a1", | ||
+ | e("c",n( | ||
+ | e("d","..."), | ||
+ | e("d",attr( //l()= explicit leaf generator for attribute assignments | ||
+ | l("<xml>..</xml>"), | ||
+ | a("w",".."))))))), | ||
+ | e("b",attr( | ||
+ | n("1:/2"), | ||
+ | a("w","...")))), | ||
+ | a("x","http://org.acme:8080"),a("y","<a>...</a>")); | ||
+ | |||
+ | </source> | ||
+ | |||
+ | We can of course mix object-oriented and functional style. | ||
+ | |||
+ | ==Traversing Trees== | ||
+ | |||
+ | ==XML Bindings== |
Revision as of 09:49, 18 December 2012
The Tree Library implements a model of edge-labelled trees, and related tools. It is a shared dependency for the components of a subsystem that provides data access under this model, including the Tree Manager services, the Tree Manager Framework, the Tree Manager Library and its clients.
The library is available in our Maven repositories with the following coordinates:
<groupId>org.gcube.data.access</groupId> <artifactId>trees</artifactId> <version>...</version>
Sources and documentation are also available in the repositories as secondary artefacts with classifiers sources
and javadoc
, respectively:
<groupId>org.gcube.data.access</groupId> <artifactId>trees</artifactId> <classifier>sources</code> <version>...</version> <groupId>org.gcube.data.access</groupId> <artifactId>trees</artifactId> <classifier>javadoc</code> <version>...</version>
Trees
The library implements a model of node-attributed, leaf-valued , edge-labelled, and directed trees. In particular:
- nodes may have an identifier and a number of uniquely named attributes;
- edges have a label;
- leaves may have a value;
- roots may identify the source of origin.
Moreover:
- identifiers, attributes, and leaves have text values;
- attribute names and labels may be namespaced.
The model is implemented in code by the following classes:
Nodes are either InnerNode
s or Leaf
s. InnerNode
s have zero or more Edge
s, each of which has a label and target Node
. Attributes and identifiers are common to all Node
s, while only Leaf
s have values. Tree
s are InnerNode
s with source identifiers, and serve as tree roots.
Instances of model classes are mutable, in that we can:
- add and remove attributes and edges;
- change the value of attributes and leaves;
- change source identifiers;
Note however that node identifiers and edge labels are assigned at creation time and cannot be changed thereafter.
We can also:
- compare instances for equivalence (instances override
equals()
); - use them as keys in hash-based structures (instances override
hashcode()
); - publish their state for debugging purposes (instances override
toString()
).
Building Trees
We can construct trees in a standard object-oriented fashion, using any of the overloaded constructors common to all model classes (including copy constructors), e.g:
Tree tree = new Tree("rootId"); tree.setAttribute(new QName("x"),"1"); tree.setAttribute(new QName("http://foo.org","y"), new Date().toString()); tree.setSourceID("sourceId"); Leaf leaf1 = new Leaf("id1"); leaf1.value("1"); Leaf leaf2 = new Leaf("id2"); leaf2.value("true"); Edge e1 = new Edge(new QName("a"),leaf1); //unqualified Edge e2 = new Edge(new QName("http://bar.org","b"),leaf2); tree.add(e1,e2)
Overloaded constructors simplify object creation, e.g.:
Tree tree = new Tree("rootId", new Edge("a", new Leaf("id1","2")), new Edge("http://bar.org","b", new Leaf("id2","true"))); tree.setAttribute("x","1"); tree.setAttribute("http://foo.org","y", new Date().toString()); tree.setSourceID("sourceId");
We find details on individual constructor and mutators in the in Javadoc documentation.
Alternatively, we can adopt a more functional style importing the static builder methods of the Nodes
class and composing them in tree expressions, e.g:
import static org.gcube.data.trees.data.Nodes.*; … Tree tree = attr(t("sourceId","rootId", e("a",1), e("http://bar.org","b",true)), a("x",1),a("http://foo.org","y",new Date()));
The functional style is far less verbose, and is particularly suited for testing. t()
, attr()
, e()
, and a()
are examples of root, attribute, and edge builders, respectively. We use them to inline tree expressions, i.e. avoid the new
operator for Node
s, Edge
s and QName
s. They also perform object-to-string conversion (cf. int
, boolean
, and Date
above).
We find details on all the available builders in the Javadoc documentation of the Nodes class. See also these additional examples:
// n() is an inner node generator Tree tree = t("rootId", e("a", n("2", e("b",3)))); tree = t( e("a", attr( n("2", e("b",l("3",0)), //l()= explicit leaf generator for identity assignment e("a",l("4",0))), a("foo","0")))); tree = attr(t("1", e("a",l("2",5)), e("b",attr( n("3",e("c",4)), a("foo",0))), e("c",5)), a("x",0)); tree = attr(t("1", e("a", n("2", e("b",n("$2")))), e("a",n("a1", e("c",n( e("d","..."), e("d",attr( //l()= explicit leaf generator for attribute assignments l("<xml>..</xml>"), a("w",".."))))))), e("b",attr( n("1:/2"), a("w","...")))), a("x","http://org.acme:8080"),a("y","<a>...</a>"));
We can of course mix object-oriented and functional style.