Program: 101550
Project: 101550
Buggy source:
/** 
 * Get the canonical text from an osis document consisting of a single fragment. The document is assumed to be valid OSIS2.0 XML. While xml valid is rigidly defined as meaning that an xml parser can validate the document, it does not mean that the document is valid OSIS. This is a semantic problem that is not validated. This method assumes that the root element is also semantically valid. <p>This means that the top level element's tagname is osis. This can contain either a osisText or an osisCorpus. If it is an osisCorpus, then it contains an osisText. However, as a simplification, since JSword constructs the whole doc for the fragment, osisCorpus can be ignored. <p>The osisText element contains a div element that is either a container or a milestone. Again, JSword is providing the div element and it will be provided as a container. It is this div that "contains" the actual fragment.</p> <p>A verse element may either be a container or a milestone. Sword OSIS books differ in whether they provide the verse element. Most do not. The few that do are using the container model, but it has been proposed that milestones are the best practice.</p> <p>The fragment may contain elements that are not a part of the original text. These are things such as notes.</p> <p>Milestones require special handling. Beginning milestones elements have an sID attribute, while ending milestones have an eID with the same value as the opening. So everything between the start and the corresponding end is the content of the element. Also, for a given element, say div, they have to be properly nested as if they were container elements.</p>
 * @param root the whole osis document.
 * @return The canonical text without markup
 */
public static String getCanonicalText(Element root){
  StringBuffer buffer=new StringBuffer();
  List frag=OSISUtil.getFragment(root);
  Iterator dit=frag.iterator();
  String sID=null;
  Object data=null;
  Element ele=null;
  while (dit.hasNext()) {
    data=dit.next();
    if (data instanceof Element) {
      ele=(Element)data;
      if (!isCanonical(ele)) {
        continue;
      }
      if (ele.getName().equals(OSISUtil.OSIS_ELEMENT_VERSE)) {
        sID=ele.getAttributeValue(OSISUtil.OSIS_ATTR_SID);
      }
      if (sID != null) {
        getCanonicalContent(ele,sID,dit,buffer);
      }
 else {
        getCanonicalContent(ele,null,ele.getContent().iterator(),buffer);
      }
    }
 else     if (data instanceof Text) {
      buffer.append(((Text)data).getText());
    }
  }
  return buffer.toString().trim();
}

Fixed version (ground truth):
/** 
 * Get the canonical text from an osis document consisting of a single fragment. The document is assumed to be valid OSIS2.0 XML. While xml valid is rigidly defined as meaning that an xml parser can validate the document, it does not mean that the document is valid OSIS. This is a semantic problem that is not validated. This method assumes that the root element is also semantically valid. <p>This means that the top level element's tagname is osis. This can contain either a osisText or an osisCorpus. If it is an osisCorpus, then it contains an osisText. However, as a simplification, since JSword constructs the whole doc for the fragment, osisCorpus can be ignored. <p>The osisText element contains a div element that is either a container or a milestone. Again, JSword is providing the div element and it will be provided as a container. It is this div that "contains" the actual fragment.</p> <p>A verse element may either be a container or a milestone. Sword OSIS books differ in whether they provide the verse element. Most do not. The few that do are using the container model, but it has been proposed that milestones are the best practice.</p> <p>The fragment may contain elements that are not a part of the original text. These are things such as notes.</p> <p>Milestones require special handling. Beginning milestones elements have an sID attribute, while ending milestones have an eID with the same value as the opening. So everything between the start and the corresponding end is the content of the element. Also, for a given element, say div, they have to be properly nested as if they were container elements.</p>
 * @param root the whole osis document.
 * @return The canonical text without markup
 */
public static String getCanonicalText(Element root){
  StringBuffer buffer=new StringBuffer();
  List frag=OSISUtil.getFragment(root);
  Iterator dit=frag.iterator();
  String sID=null;
  Object data=null;
  Element ele=null;
  while (dit.hasNext()) {
    data=dit.next();
    if (data instanceof Element) {
      ele=(Element)data;
      if (!isCanonical(ele)) {
        continue;
      }
      if (ele.getName().equals(OSISUtil.OSIS_ELEMENT_VERSE)) {
        sID=ele.getAttributeValue(OSISUtil.OSIS_ATTR_SID);
      }
      if (sID != null) {
        getCanonicalContent(ele,sID,dit,buffer);
      }
 else {
        getCanonicalContent(ele,null,ele.getContent().iterator(),buffer);
      }
    }
 else     if (data instanceof Text) {
      int lastIndex=buffer.length() - 1;
      String text=((Text)data).getText();
      if (lastIndex >= 0 && !Character.isWhitespace(buffer.charAt(lastIndex)) && !Character.isWhitespace(text.charAt(0))) {
        buffer.append(' ');
      }
      buffer.append(text);
    }
  }
  return buffer.toString().trim();
}