Overview
Archie is a "hierarchical object storage" toolkit - in fact, "Archie" stands
for "hierarchy". The Ubik
distributed computing framework uses Archie to support its JNDI implementation.
Features
- Objects are bound to names in a hierarchical datastructure;
- hierarchy traversal strategies are decoupled from datastructure (allows
implementing you own strategies);
- interface-based design: roll your own (you could for example easily back
your implementation with an object-oriented database);
- convenient in lots of situations (isn't Log4j using such a hierarchy
internally? internationalization could also be a candidate...);
- provides a basic JNDI implementation that can easily be augmented if needed.
Design
Get the following and you're off:
- A hierarchy is a tree of Nodes.
- A hierarchy has a single root Node.
- Nodes of a given type are instantiated by a
NodeFactory.
- A NameParser parses strings
into Names.
- A Name is composed of one to many NamePart(s).
- The "local name" of a node is modeled as a NamePart. The local name of a node is unique in the context
of that node's parent.
- The "absolute path" of a node is in fact its full path in the node hierarchy; that path is the node's full-qualified
Name.
- You can manipulate nodes yourself, but most of the time you'll use an
Archie instance to do so.
Learning by Example
The examples below should prove a thorough enough introduction. For more
details, see the javadoc and the test cases.
Archie API
Creating a Hierarchie from Scratch
import org.sapia.archie.*
import org.sapia.archie.impl.DefaultNodeFactory;
...
NodeFactory fac = new DefaultNodeFactory();
// note that the Archie class only needs the root node.
// the Node interface provides all the functionality that
// the Archie class needs to create, lookup and remove nodes.
Archie arch = new Archie(fac.newNode());
..
|
Binding an Object
NameParser parser = arch.getNameParser();
Name name = parser.parse("some/path/foo");
// No, class Foo is not in the API, don't look for it...
arch.bind(name, new Foo());
|
Looking Up
With archie, you can lookup objects, nodes, and you can
use/implement lookup strategies.
NameParser parser = arch.getNameParser();
// looking up an object...
Name name = parser.parse("some/path/foo");
Foo f = (Foo)arch.lookup(name);
// looking up a node...
Name name = parser.parse("some/path");
Node node = arch.lookupNode(name);
f = (Foo)node.getValue(parser.parseNamePart("foo"));
// using some lookup strategy: this one would lookup
// a value at a given node - under a given name, and
// go up to the parent nodes if no value would be found
// at that node, under that name.
ReverseLookupStrategy reverse = new ReverseLookupStrategy();
Foo f = (Foo)reverse.lookup(n, arch.getRoot());
|
Removing an Object
NameParser parser = arch.getNameParser();
Name name = parser.parse("some/path/foo");
// No, class Foo is not in the API, don't look for it...
arch.unbind(name);
|
You get the picture... see the javadoc for more info.
JNDI
Archie provides a basic JNDI implementation (not yet supporting
the Referenceable interface, links, listeners, etc.
Usage
The following snippet illustrates how to obtain a JNDI context implemented
on top of Archie:
import org.sapia.archie.impl.DefaultNodeFactory;
import org.sapia.archie.jndi.JndiContext;
import javax.naming.Context;
..
NodeFactory fac = new DefaultNodeFactory();
Context ctx = new JndiContext(fac);
...
|
From then on, you use the JNDI API as you do normally. Of course, instantiating
a JNDI Context like this is not standard practice. Rather,
you should implement your own InitialContextFactory.
Conclusion
Use Archie to store objects hierarchically. Implement your own lookup strategies, you own nodes, etc. Or use Archie as the basis
for a JNDI provider.
|