[jdom-interest] suggested JDOM2 improvements

Rolf Lear jdom at tuis.net
Tue Jan 17 05:42:59 PST 2012


Hi Thomas.

Interesting Feedback. A lot to respond to... not complaining ;-)



First, the easy thing: XPath and thread-safety.... it will never happen.
There's just too much to 'require', not the least of which would be that
all of JDOM would need to be thread-safe. For example, someone modifying an
Element's content in one thread while that same Element is being queried
(XPath) in another. Some things would make sense to be Thread-safe
(Namespace class is...), but in the case of XPath it would just never
happen. Additionally, our default XPath 'engine' Jaxen makes no claims
about being thread-safe.

If thread-safety is not an 'intrinsic' property of XPath, then there is no
real sense in making it 'immutable' if it removes 'convenience'.

In the 'simple' XPath case (no extra namespaces, no Variables) XPath is
still a 1-liner, which is hard to beat. In a complicated case I see more
complexity trying to 'massage' your Namespaces and Variables in to some new
type structures (the varargs) than the existing concept of adding
Namespaces and setting variables.

Also, keeping backward compatibility is a strong consideration.

In reality I think I would like to see code examples of what you think it
'should' look like to get a better idea, but at the moment i am not
convinced that it's actually broken enough to require fixing.



Right, what about the generics and XPath return types....? Well, this is a
complicated one, and I thought about it hard. The problem boils down to the
fact that XPath expressions can return Boolean, Double, and String in
addition to whatever JDOM nodes are selected. There is no common 'base' to
selectNodes results other than 'Object'. Really!

This means that XPath has to be *able* to return List<?> (but not
necessarily always). There is no option.

This problem is what inspired a lot of the Filters class, because the
List<?> return type is not convenient, yet it can be coerced into something
that *is* convenient. The Filter instances do full type (and other)
checking on the values in the List and not only re-casts the generic type
of the result, but it also 'silently' removes any content that cannot be
coerced.

Thus my intention was that people would do things like:

XPathFactory xpfactory = XPathFactory.newInstance();
XPath xpath = xpfactory.compile("//*");
List<Element> nodes =
Filters.element().filter(xpath.selectNodes(document));

I can see that this model could be modified somewhat to put the filter in
at the XPath compile time to become something like:

XPathFactory xpfactory = XPathFactory.newInstance();
XPath<Element> xpath = xpfactory.compile("//*", Filter.element());
List<Element> nodes = xpath.selectNodes(document);

I think that is a valuable modification, and it is nice because the
compile(String) would return XPath<?>, and the compile(String, Filter<E>)
would return XPath<E>. This would all still be backward compatible with
JDOM 1.x

Filed issue #58




JDOMConstants. Hmmm, I think that shows my 'age'. It is a kick-back to
when import-static was not available. Old habits and so on. Point taken ...
;-). It should be an easy change. Filed Issue #59



Finally, the ContentList in Element. I am getting to it.... doing some
tidy-up first. Javadoc mostly. This will be a relatively big change, and
impacts all 'custom' JDOM implementations. It is not a certainty yet for
JDOM2.


Thanks for the feedback. Appreciate it!

Rolf


On Tue, 17 Jan 2012 09:10:00 +0100, Thomas Scheffler
<thomas.scheffler at uni-jena.de> wrote:
> Hi,
> 
> first I want to thank all on working on JDOM2. While going over the 
> Javadocs I noticed some issues and got some ideas I want to share.
> 
> When creating a XPath instance, the instance should be unmodifiable,
e.g.
> 
> remove setNamespace() methods and use
> 
> XPathFactory.newInstance().compile(String xpath, Namespace...
namespaces)
> 
> One thing that is left then is variables and XPath instances should be 
> threadsafe then. One way to achieve this would be to create a 
> XPathVariable class and use var-args on selectNodes:
> 
> xPath.selectNodes(NamespaceAware context, XPathVariable... variables)
> 
> Then you can improve the XPathFactory on using a weak cache that always 
> returns the same instance. This would not only allow to share a XPath 
> instance across multiple threads but also decrease memory consumption.
> 
> ----
> 
> What I would take into consideration is allow generics in XPath, e.g.
> 
> XPath<Element> test=XPath.newInstance("/foo/bar", SOME_ELEMENT_HINT);
> XPath<Attribute> test2=XPath.newInstance("/foo/@bar",
SOME_ATTRIBUTE_HINT);
> 
> Or if you do not want this, you can return <? extends NamespaceAware> by

> default.
> 
> ----
> 
> One other thing I noticed is the practice of making JDOMConstants an 
> interface. Usually interface means something like
> 
> if (o instanceof (JDOMConstants)){
> 	((JDOMConstance)o).doSomething();
> }
> 
> It would be "better" code to make JDOMConstants a final class with 
> private constructor and use "import static JDOMConstants.*" where you 
> need it. That would not result in such statements: "Element _is a_ 
> JDOMConstants".
> 
> ----
> 
> And before starting another mail, please count my vote on moving 
> ContentList into Element.
> 
> I'm really looking forward to JDOM2 release.
> 
> regards Thomas


More information about the jdom-interest mailing list