[jdom-interest] suggested JDOM2 improvements

Rolf Lear jdom at tuis.net
Fri Jan 20 07:16:16 PST 2012


I agree with the debug issue. That is exactly why in the model I intend to
provide I will make it possible to return the 'XPathResult<T>' and not just
a List<T>.
The XPathResult<T> will allow you to inspect the base XPath results in a
List<Object> as well as the filter results in the List<T> format.

XPath has always been a vulnerable area for type-casting. Nothing has
stopped the user from coding inappropriate casts for XPath results. With
JDOM2 the user will have the option of trading class-cast-exceptions for
missing result conditions. If the user is anxious to keep the
class-cast-exception option then they can choose to use unfiltered XPath
results.

In general, a user writing an XPath expression has to know ahead of time
what the return types will be (including XPath 2.0 with it's plethora of
atomic types). Using the Filter concept allows the user to anticipate the
type of his/her choice, and not have to statically build the type in to the
API.

Mitigating the debug issue with a XPathResult<T> with useful methods
interrogating intermediate results (and a useful toString()) is a good
compromise, I think.

As long as people understand that the XPath results are 'filtered' a
second time then everything should be fine.

Remember that the users can always elect to have unfiltered results too,
but then they have to live with List<Object> results.

Rolf

On Fri, 20 Jan 2012 14:57:02 +0000, Michael Kay <mike at saxonica.com> wrote:
> Thanks for the explanation.
> 
> I wonder, though, if discarding data of the wrong type is better than 
> throwing a ClassCastException? It's very easy in XPath, for example, to 
> ask for a text node when you thought you were asking for a string. 
> Expressions that return nothing are the hardest thing to debug as it is.
> 
> Michael Kay
> Saxonica
> 
> On 20/01/2012 14:50, Rolf Lear wrote:
>> No, no static type analysis.
>>
>> JDOM has 'always' had the 'Filter' concept. You could, for example, do:
>>
>> List comments = element.getContent(new
>> ContentFilter(ContentFilter.COMMENT));
>>
>> In order to make the above 'generic' in JDOM2, the getContent() has to
>> return an appropriate type for whatever the Filter returns. I
'extended'
>> the Filter class to have a generic return type. Thus, it is now
possible
>> to:
>>
>> List<Comment>  comments = element.getContent(Filters.comment());
>>
>> The Filter implementations all follow the rules:
>> 1. if the content to be filtered does not match the filter, then the
>> content is discareded.
>> 2. if the content matches the filter, then it is explicitly cast to the
>> generic type of the filter.
>>
>> What this means is that you are guaranteed that the generic type of the
>> Filter results is accurate, and it is impossible to 'force' Filter
>> results
>> to have badly-loaded result lists.
>>
>> Filter instances can do more than just type-checking on the input data,
>> but can also do anything else to filter the content, like checking for
>> particular names, etc.
>>
>> With the XPath library, I intend to apply the same Filter concept to
the
>> XPath results.
>>
>> Since the user knows the XPath expression, they will also know the
>> anticipated return type. If they want to select Elements then they can
>> apply an Element filter. If they want to select 'everything' then
>> they can use a 'passthough' filter which 'does no filtering' (but as a
>> result can only 'cast' to Object).
>>
>> Essentially the Filter concept is a way to coerce unknown data in to a
>> user defined type while ensuring the results will never generate
>> class-cast, and providing an opportunity to discard what you do not
want.
>> It is ideal for XPath results.
>>
>> The 'user' creates their own filter
>>
http://hunterhacker.github.com/jdom/jdom2/apidocs/org/jdom2/filter/Filter.html
>> , or reuses one of the 'common' filters accessible in the 'Filters'
class
>>
http://hunterhacker.github.com/jdom/jdom2/apidocs/org/jdom2/filter/Filters.html
>>
>> Most Filter implementations take a Class instance (matching the generic
>> type of the Filter) as a constructor argument, and any values that
match
>> the filter are cast using the Class.cast() method.
>>
>> Rolf
>>
>>
>> On Fri, 20 Jan 2012 14:31:07 +0000, Michael Kay<mike at saxonica.com> 
>> wrote:
>>>> public XPathCompiled<Object>  compile(String xpath);
>>> I started introducing generics for this in Saxon 9.4 and the
experience
>>> wasn't wholly positive; it left a lot of cases where there were
warnings
>>> that needed to be ignored. That may be because I found generics to be
>>> deeper and more bewildering than I expected.
>>>
>>> It's not at all clear to me how your types such as
>>> XPathCompiled<Element>  are supposed to work. Do they rely excessively
>>> on
>>> the ability of the XPath engine to do static type analysis of the
>>> supplied expression?
>>>
>>> Michael Kay
>>> Saxonica


More information about the jdom-interest mailing list