Brian Ewins noted this on the mailing list about a year ago. Adding his comments here so we don't losr track fo them:
The one cycle that always bothers me is the one between 'Navigator' and 'XPath'.
For comparison, first here's how things work in jaxp:
//in jaxen we could use OM uris which are Navigator class names.
String uri = "urn:jaxen:my.funky.jaxen.Navigator";
XPathFactory xpf = XPathFactory.newInstance(uri);
// set up the evaluation context
XPath xpath = xpf.newXPath();
// because we have the resolvers set up we can do all var/fn resolving
// in the /parsing/ stage (unless someone made the mistake of adding
an 'eval' function!)
XPathExpression xexpr = xpath.compile(expression);
// the compiled expression needs the navigator.
// other evaluation paths are just sugar for getting the compiled
Object result1 = xexpr.evaluate(context1, returnType);
Object result2 = xexpr.evaluate(context2, returnType);
The Navigator only appeared in that as something other classes depended on,
it never depends on the public xpath api, or on the parser. Contrast
this with jaxen:
Navigator nav = new MyNavigator();
// option 1: compile using navigator
XPath xpath = nav.parseXPath(expression);
// option 2: create by hand from base xpath
XPath xpath = new BaseXPath(expression, nav);
// option 3: use OM-specific xpath implementation
XPath xpath = new MyXPath(nav);
Object result1 = xpath.stringValueOf(context1);
// jaxen has very late binding. This means that we can't do the
// lookups earlier, to eliminate constant expressions etc.
Object result2 = xpath.stringValueOf(context2);
So, "option 1" makes the navigator depend on the parser and the xpath
implementation, which in turn depends on the navigator - a cycle.
Option 3 is just sugar for option 2. Option 2 is a little grotty
compared to jaxp, a factory method returning an XPath given a string
and a navigator would be just as good.
Another cause of odd dependencies is the 'eval' function. This causes
the 'function' package to depend on 'saxpath', which depends on 'expr'
which depends on 'function'... ew. And once you're rid of 'eval',
theres no longer a reason why fc/vc need to be bound so late, allowing
Finally, theres the 'evaluate/simplify' methods in the expr package.
In order to break the dependency between the parser and the runtime,
we have saxpath calling a handler which creates objects of a given
interface, which can be evaluated directly. However, because saxpath
is borked, it really only works properly if you always create the tree
with the expr.Default* objects. An alternative approach would be to
have separate parser/evaluator packages both depending on a concrete
AST package with visitor support - all of the 'BlahExpr' classes can
be concrete so theres no need for all those interfaces to break the
cycles. However, I don't think the current split is responsible for
I think if you drop that Navigator.parseXPath method and remove the
'eval' function (which is completely unnecessary IMHO) most of the
cycles can be made to disappear.