code: public int doAfterBody() {
  
          if(hasErrors())
              return SKIP_BODY;
  
          LOGGER.debug("structured repeater: " + _haveKids + " render state: " + renderStateToString(_renderState));
  
          /*
            structured rendering of the repeater; body content is ignored and real
            content is rendered through cooperating nested tags
           */
          if(_haveKids)
              return renderStructured();
          /*
            unstructured rendering of the repeater; this means that there isn't
            a repeater(Header|Item|Footer) inside the body of the repeater.
           */
          else {
              if(bodyContent != null) {
                  addContent(bodyContent.getString());
                  bodyContent.clearBody();
              }
  
              if(_iterator.hasNext()) {
                  _currentIndex++;
                  _currentItem = _iterator.next();
  
                  if(_ignoreNulls && _currentItem == null) {
                      advanceToNonNullItem();
  
                      /* ignoring null items and no more non-null items, so skip to doEndTag() */
                      if(_currentItem == null)
                          return SKIP_BODY;
                  }
  
                  /* found another item; re-render the repeater's body */
                  return EVAL_BODY_AGAIN;
              }
              /* no more items; skip to doEndTag() */
              else return SKIP_BODY;
          }
      }
docs: <p>
  Continue rendering the repeater changing the render state or advancing to a new data item
  as needed.
  </p>
  @return {@link #SKIP_BODY} if an error occurs or the data set has been rendered; {@link #EVAL_BODY_AGAIN} otherwise