[jdom-interest] JDom and Java5

Mattias Jiderhamn mj-lists at expertsystems.se
Sat Feb 23 12:39:18 PST 2008


(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
>>
>>   
>



More information about the jdom-interest mailing list