[stringtemplate-interest] bug in first function or just a Java 5 issue?

John Snyders jjsnyders at rcn.com
Thu Oct 19 23:22:12 PDT 2006


It seems to me that the first() function has a subtle bug. This is the way
it currently is:

/** Return the first attribute if multiple valued or the attribute
 *  itself if single-valued.  Used in <names:first()>
 */
public Object first(Object attribute) {
 if ( attribute==null ) {
  return null;
 }
 Object f = attribute;
 attribute = convertAnythingIteratableToIterator(attribute);
 if ( attribute instanceof Iterator ) {
  Iterator it = (Iterator)attribute;
  if ( it.hasNext() ) {
   f = it.next();
  }
 }
 return f;
}

According to the comment if the attribute is multi valued then first() will
return the first value.
If it is not multi valued it will just return the attribute. What it doesn't
say is what happens when the
attribute is multi valued but is empty. In this case I think it should
return null but instead it returns
the attribute!

Because of the way other parts of StringTemplate work you are unlikely to
ever notice the difference between first returning null for an empty
collection attribute and the attribute itself.
If the attribute is iterable and empty using $first(attribte)$ is OK because
iterating over the empty collection will produce no output.
$length(first(attribute)$ is also OK because length has special checks for
various kinds of collections. The same is true of $if(first(attribute)$

So if you can't tell the difference why is it affecting me? Because I am
using Java 5 and made some changes so that ST would understand the Iterable
interface. (see
http://www.antlr.org:8080/pipermail/stringtemplate-interest/2006-October/000
728.html) Now I have an attribute passed into ST that is Iterable (according
to my updated convertAnythingIteratableToIterator) but there are no special
cases in length() and if(). So when my interable object that is not a
collection was empty $if(!attribute)$ didn't detect it and neither did
$if(!first(attribute))$.

Something that is iterable but not a collection could have other intersting
properties so I'm not sure I would want $if(!attribute)$ to return true when
it is empty.

At this point I'm not sure if I should change my iterable class, fix first
as described below or change if() and length to match my change to
convertAnythingIteratableToIterator.

The last() function has the same "problem".

I fixed first by changing

  if ( it.hasNext() ) {
   f = it.next();
  }
to
  if ( it.hasNext() ) {
   f = it.next();
  }
  else {
   return null;
  }

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org:8080/pipermail/stringtemplate-interest/attachments/20061020/f511f315/attachment.html 


More information about the stringtemplate-interest mailing list