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