[jdom-interest] JDom and Java5
Victor Toni
victor.toni at ebuconnect.de
Tue Feb 26 04:57:19 PST 2008
Hi Rolf,
have you tried the approach I mentioned in the previous mail. It doesn't
seem to impose changes on the user but gives him flexibility.
For convenience the mentioned code snippet:
public <T> List<T> selectNodes(Object context) throws JDOMException {
try {
currentContext = context;
return xPath.selectNodes(context);
} catch (JaxenException ex1) {
throw new JDOMException("XPath error while evaluating \"" +
xPath.toString() + "\": " + ex1.getMessage(), ex1);
} finally {
currentContext = null;
}
}
Kindest regards,
Victor
Rolf Lear wrote:
> Hi All.
>
> I spent a fair bit of time playing with things over the weekend, and
> have decided that making generic versions of the selectNodes process
> is somewhat possible if we change the API a lot, but, at some point
> there has to be an explicit cast of either the content of a list, or
> the list itself. Currently there are no Compiler errors or warnings in
> the Java5 JDom, and these changes would require us to tolerate a
> compiler warning at some point. As long as we use Jaxen I see no
> alternative. Then again, someone may take an approach different to the
> ones I have tried, and come up with something that works well.
>
> The alternatives as I see them are:
> a) explicitly casting the returned List from Jaxen to a List<type>,
> and then returning the List<type> to the user, at which point, if
> there is a mismatch between the content type the user claims is in the
> list, and the actual content of the list, then there will be a
> ClassCastException when the user reads the List<type>. I see this as
> being unacceptable. A modification to this would be to check each
> element of the list before returning it to the user at which point the
> ClassCastException will happen inside the JDom API and this would be
> better, but also add a processing overhead and require a significant
> (not recompile-compatible) change to the API method signatures.
> b) creating a List<Type> and then checking and casting each element of
> the Jaxen List result, and adding these to the List<Type>, but will
> add a processing overhead. This will also require
> non-recompile-compatible changes to the API.
>
> For the moment I am giving up on trying to get a clean way to
> transform the data in to a more meaningful result. "The Right Thing"
> is hard to guarantee without big API changes as far as I can tell.
>
> It would be great if someone else could give it a go to confirm this.
>
> For the moment I am leaving the code unchanged to return List<?> until
> someone comes up with something better.
>
> Rolf
>
> Rolf wrote:
>> Hi Mattias.
>>
>> Thanks for that. I's made me look further in to things than I had
>> before. I put together some test code and I see what you mean about
>> casting the results. I have been in the habit of coding using
>> eclipse, and I set strict compiler warnings and as a result I see
>> lots of errors/warnings generated by eclipse. I always try to resolve
>> every issue in my code..... and using raw types always produces
>> warnings. This would explain my reluctance for returning just plain
>> List. It is a raw type and should be avoided. At the same time, I
>> realize now that returning List<Object> has it's drawbacks in that
>> you can't cast it to anything directly either... although you can
>> actually get away with a double-cast .... List<Element> mylist =
>> (List<Element>)(List<?>)(new ArrayList<Object>());
>>
>> By using plain List it introduces compile-time warnings in to JDom. I
>> would prefer to avoid that at all costs. It should be the client side
>> that encounters the warnings, not the API side.
>>
>> I am content with returning List<?> or List<? extends Object> for the
>> return type. It indicates that the process has been thought through.
>> It would also be real interesting to explore turning the entire XPath
>> class in to a generic object.... I'm going to play a little bit and
>> get back.
>>
>> I think there is a fair amount of food for thought. Right now the API
>> returns List<?> and this should remove any compile-time issues anyone
>> has with the jar, so, for those interested, it is not a hurdle....
>>
>> Rolf
>>
>> Mattias Jiderhamn wrote:
>>> (To be completely honest I have not read the whole post Rolf...)
>>>
>>> Without having analyzed if this depends on some compiler parameter
>>> or other project setting, here is what I experienced.
>>>
>>> With return type List (as JDOM is today) I could do
>>> List<Element> elements = XPath.selectNodes(doc, path)
>>> and only get compiler warnings
>>>
>>> With return type List<?> (Rolfs second version; which I believe are
>>> equivalent to List<? extends Object>) I could do
>>> List<Element> elements = (List<Element>) XPath.selectNodes(doc, path)
>>>
>>> With return type List<Object> I cannot cast but have to do
>>> List<Element> elements = new ArrayList<Element>();
>>> for(Object o : XPath.selectNodes(doc, path))
>>> elements.add((Element)o);
>>>
>>> I think the last option is by far the least appealing (unless, as I
>>> said, there is some setting to fix this).
>>> In the choice between List and List<?>/List<? extends Object> the
>>> plain List has the advantage of making the Java5 port more of a JAR
>>> replacement. It does not require modifying the code to add the cast.
>>> Also, Gregor points out that List is for "pre-generics legacy code"
>>> and certainly, in this case it could be used to indicate that
>>> behinds the scenes there is pre-generics legacy code, which in this
>>> case is Jaxen.
>>>
>>> Therefore I personally vote for "List".
>>>
>>> BUT there is actually a fourth alternative; add the expected output
>>> type as a parameter to the method.
>>> List<Element> elements = XPath.selectNodes(doc, path, Element.class);
>>> List<Attribute> elements = XPath.selectNodes(doc, path,
>>> Attribute.class);
>>> List<Object> elements = XPath.selectNodes(doc, path, Object.class);
>>> // Mix of different types
>>> This may be the most beautiful solution, but also the most
>>> noticeable change with a new parameter. What about an overload with
>>> one legacy version with List and one with the third parameter???
>>>
>>> /Mattias
>>>
>>>
>>> Rolf wrote (2008-02-23 15:51):
>>>> Hi Gregor
>>>>
>>>> Hmm... actually, I somewhat disagree (in this particular
>>>> circumstance). I have been thinking about this a bit more
>>>>
>>>> Here's the 'current' code behind the method (after I modified it
>>>> yesterday)...
>>>>
>>>> public List<?> selectNodes(Object context) throws JDOMException {
>>>> try {
>>>> currentContext = context;
>>>> return xPath.selectNodes(context);
>>>> } catch (JaxenException ex1) {
>>>> throw new JDOMException("XPath error while evaluating \"" +
>>>> xPath.toString() + "\": " + ex1.getMessage(), ex1);
>>>> } finally {
>>>> currentContext = null;
>>>> }
>>>> }
>>>>
>>>> Here's the signature on the xPath method that is supplied by Jaxen:
>>>>
>>>> List <http://java.sun.com/j2se/1.4.2/docs/api/java/util/List.html>
>>>> *selectNodes*(Object
>>>> <http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html>
>>>> context) throws JaxenException
>>>> <http://jaxen.codehaus.org/apidocs/org/jaxen/JaxenException.html>
>>>>
>>>> Given that XPath can return all sorts of values (not all of them
>>>> are JDom Content (like Attribute which is not Content)), then we
>>>> have a real problem with this method.
>>>>
>>>> There is no way I can see (even by modifying Jaxen) to return a
>>>> list of any specific type other than Object. It would be real nice
>>>> if an xpath that returned just Elements would have a return type of
>>>> List<Element>, but that just isn't feasible.
>>>>
>>>> The next best thing is to return something appropriate, and that
>>>> should be the same as what Jaxen would return if it were Generified.
>>>>
>>>> Thus, the best thing would be to consider things from Jaxen's POV,
>>>> and let the 'client' sort it out.
>>>>
>>>> Since Jaxen does not know anything about the actual content in the
>>>> 'context' (it is all delegated to a JDom specific implementation),
>>>> and that implementation has to be able to return both Attribute and
>>>> Content, the best that Jaxen could do is return List<Object>.
>>>>
>>>> The Jaxen code would have no option but to look something like:
>>>>
>>>> List<Object> ret = new XXXList<Object>();
>>>> for (..... nodes in context ...) {
>>>> if (... node matches the xpath ...) {
>>>> ret.add(node);
>>>> }
>>>> }
>>>>
>>>>
>>>> because it will potentially have to add Attributes, Elements, Text,
>>>> etc. (and that's just for JDom, for other API's it will need other
>>>> constructs).
>>>>
>>>> As a consequence, the Jaxen code, if it were Generified, would have
>>>> no option but to return List<Object> from the method, just like it
>>>> returns Object from the method selectSingleNode();
>>>>
>>>> Object
>>>> <http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html>
>>>> *selectSingleNode*(Object
>>>> <http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html>
>>>> context) throws JaxenException
>>>> <http://jaxen.codehaus.org/apidocs/org/jaxen/JaxenException.html>
>>>>
>>>> In other words, I have come back around the circle and I believe
>>>> that the method should return exactly List<Object> rather than
>>>> List<?> or List<? extends Object>.
>>>>
>>>> As further considerations against the alternatives:
>>>>
>>>> returning List<? extends Object> implies that the actual returned
>>>> list may be any other specific type as well, e.g. List<String> or
>>>> List<Element> or even something silly like List<System>. This will
>>>> not be the case, the actual returned type will in fact be
>>>> List<Object> and there is no point in making it more obscure by
>>>> saying List<? extends Object> because that actually reduces the
>>>> meaning.
>>>>
>>>> returning List<?> implies that we have no idea what's in the list,
>>>> but we do.
>>>>
>>>> The logical answer appears to be returning List<Object>. This makes
>>>> the most sense until Jaxen finds a way for the method
>>>> returnSingleNode(Context) to return a type other than Object.
>>>> Here's the Jaxen code:
>>>>
>>>> public Object selectSingleNode(Object node) throws JaxenException {
>>>> List results = selectNodes( node );
>>>> if ( results.isEmpty() ) {
>>>> return null;
>>>> }
>>>> return results.get( 0 );
>>>> }
>>>>
>>>> If Jaxen can be generified to have something like:
>>>>
>>>> public T <T extends Object> selectSingleNode(Object node) throws
>>>> JaxenException {
>>>> List<T> results = selectNodes( node );
>>>> if ( results.isEmpty() ) {
>>>> return null;
>>>> }
>>>> return results.get( 0 );
>>>> }
>>>>
>>>> only then should we consider the alternatives....
>>>>
>>>> On the other hand, the client-side code calling the XPath method is
>>>> going to have to jump through all sorts of instanceof hoops
>>>> anyways, and the return type does not really affect that in any way.
>>>>
>>>> As for Mattias's original claim that List<?> can be cast to
>>>> List<Element> if you know the content will be only Elements, then,
>>>> I believe that lends a certain weight to List<?>, but, is the same
>>>> not true for List<Object>? At some point you will have a
>>>> compile-time warning about unchecked types... unless you do
>>>> individual casts to Element on the contents of the List anyway.
>>>>
>>>> Does this make sense? This whole topic is somewhat interesting, and
>>>> I do see the value in different implementations. There appears to
>>>> be more than one right answer, all with different compromises. At
>>>> the moment I am more in the List<Object> camp but am willing to be
>>>> convinced otherwise....
>>>>
>>>> Rolf
>>>>
>>>> Gregor Zeitlinger wrote:
>>>>> I think List<? extends Object> is more appropriate.
>>>>>
>>>>> It shows that the code has been generified (as opposed to using a
>>>>> plain List).
>>>>> It's similiar to List<?>, but shows that Object is indeed the least
>>>>> common denomiator.
>>>>> _______________________________________________
>>>>> To control your jdom-interest membership:
>>>>> http://www.jdom.org/mailman/options/jdom-interest/youraddr@yourhost.com
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>> _______________________________________________
>> To control your jdom-interest membership:
>> http://www.jdom.org/mailman/options/jdom-interest/youraddr@yourhost.com
>>
>
>
> _______________________________________________
> To control your jdom-interest membership:
> http://www.jdom.org/mailman/options/jdom-interest/youraddr@yourhost.com
--
Victor Toni
Senior Software Architect
Phone: +49 203 9414768
Office: +49 2181 2363-0
Fax: +49 2181 2363-43
Mobile: +49 160 8511835
Web: www.ebuconnect.de
Mail: victor.toni at ebuconnect.de
Sitz der Gesellschaft: ebuconnect AG, Stadttor 1, D-40219 Düsseldorf Amtsgericht Düsseldorf: HRB 40219
Vorstand: Andreas Weiss - Vorsitzender
Vorsitzender des Aufsichtsrates: Dr. Marc Henze
More information about the jdom-interest
mailing list