Knut,

Knut Wannheden <[EMAIL PROTECTED]> wrote:

Dmitri,

Dmitri Plotnikov apache.org> writes:

> 
> You are right - I am starting to forget everything. The node set does not 
> have to be ordered, but if I want to implement axes like "preceding" and 
> "following", I have to impose some order on the object properties.
> 

What does this mean for JXPath? Does the ordering only ever have to take place
in PredicateContext?

I don't think there is any ordering in PredicateContext.  The ordering of 
properties is done by JXPathBasicBeanInfo, the ordering of keys in maps is done 
by DynamicPropertyPointer.


> The advice I have given in similar situations before was always the same: 
> You have at least three options:
> 1. Provide custom BeanInfo that excludes upward going links, e.g. keep the 
> link from Window to Widget, but hide the link from Widget to Window.
> 2. Create custom implementations of NodePointer and NodePointerFactory 
> (which seems to be exactly what you are doing)
> 3. (IMO, the best) avoid using JXPath for extensive searches altogether - it 
> is not designed to handle them. It can show horrific performance, which is 
> exactly what you are observing. Systems like Xalan do much better because 
> they work with static structures that they index prior to the evaluation of 
> XPaths. Try either using specific paths like "/a/b/c" or utilize indexing 
> with IdentityManager or KeyManager; or use a custom extension function to 
> perform the search.
> 

I will try to go with option 2 as I don't think 3 really is an option; or what
other tool would let me evaluate XPaths against Java object graphs?

I don't worry about the performance too much as the queries will be run by a
user through a GUI. What is problematic is the fact that the call to
Iterator#hasNext(), depending on the expression and object graph, is 
potentially long running and can't be interrupted. Long running not because
JXPath couldn't yet determine if there is a next node or not, but because it
decided to prefetch and order *all* nodes which will be returned by subsequent
calls to Iterator#next().

In my case I found that this prefetching and ordering takes place in
ChildContext#constructIterator(). This method is called by
EvalContext#hasNext(), because it determined that the nodes need to be
prefetched since the ChildContext's parent context is a DescendantContext, 
which requires child ordering (in document order).

Now I hope you can see where my problem lies and why I initially asked about 
the interpretation of XPath node-sets. After browsing the source code I think 
I now understand why it works the way it works. What if the ordering (forward
and backward) were entirely left up to the NodeIterators? Would that solve the
problem?

Meanwhile, to be able to interrupt JXPath, I will implement my own NodePointer
throwing an unchecked exception to abort JXPath. (I tried this in the
NodePointerFactory, but there the exception is caught and ignored.)

Ok, I think I now get it. Sorry about having been so obtuse.  To make the 
search interruptable, we should eliminate the isChildOrderingRequired method. 
Actually I don't even know why we have it. Paths like "//foo" would produce 
results in the right order even without it.

Try this: comment out the DescendantContext#isChildOrderingRequired method.  
Let me know if it makes a difference.  If it does without breaking anything 
else, I will make the change permanent.


Regards,

--knut



Best,

- Dmitri

Reply via email to