gt:     for (int i = _children.size() - 1; i >= 0; i--) {
context: /*
   * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
   *
   * This file is part of Resin(R) Open Source
   *
   * Each copy or derived work must preserve the copyright notice and this
   * notice unmodified.
   *
   * Resin Open Source is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * Resin Open Source is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
   * of NON-INFRINGEMENT.  See the GNU General Public License for more
   * details.
   *
   * You should have received a copy of the GNU General Public License
   * along with Resin Open Source; if not, write to the
   *   Free SoftwareFoundation, Inc.
   *   59 Temple Place, Suite 330
   *   Boston, MA 02111-1307  USA
   *
   * @author Scott Ferguson
   */
  
  package com.caucho.jsp.java;
  
  import com.caucho.jsp.JspParseException;
  import com.caucho.util.CharBuffer;
  import com.caucho.util.L10N;
  import com.caucho.util.LineCompileException;
  import com.caucho.vfs.WriteStream;
  import com.caucho.xml.QName;
  import com.caucho.xml.XmlChar;
  
  import java.io.IOException;
  import java.util.ArrayList;
  
  /**
   * A node which can contain other nodes.
   */
  public abstract class JspContainerNode extends JspNode {
    static final L10N L = new L10N(JspContainerNode.class);
    
    protected ArrayList<QName> _attributeNames = new ArrayList<QName>();
    protected ArrayList<Object> _attributeValues = new ArrayList<Object>();
    
    protected ArrayList<JspNode> _children = new ArrayList<JspNode>();
  
    private ArrayList<JspAttribute> _attrChildren;
  
    protected boolean _hasJspAttribute;
    
    /**
     * Adds an attribute.
     *
     * @param name the name of the attribute.
     * @param value the value of the attribute.
     */
    @Override
    public void addAttribute(QName name, String value)
      throws JspParseException
    {
      if (name == null)
        throw new NullPointerException();
  
      if (_attributeNames.indexOf(name) >= 0)
        throw error(L.l("'{0}' is a duplicate attribute name.  Attributes must occur only once in a tag.", name.getName()));
      
      _attributeNames.add(name);
      _attributeValues.add(value);
    }
  
    /**
     * Adds a JspAttribute attribute.
     *
     * @param name the name of the attribute.
     * @param value the value of the attribute.
     */
    @Override
    public void addAttribute(QName name, JspAttribute value)
      throws JspParseException
    {
      if (name == null)
        throw new NullPointerException();
      
      if (_attributeNames.indexOf(name) >= 0)
        throw error(L.l("'{0}' is a duplicate attribute name.  Attributes must occur only once in a tag.", name.getName()));
      
      _attributeNames.add(name);
      _attributeValues.add(value);
  
      _gen.addFragment(value);
    }
  
    /**
     * Returns the named attribute.
     */
    public Object getAttribute(String name)
      throws JspParseException
    {
      for (int i = 0; i < _attributeNames.size(); i++) {
        if (name.equals(_attributeNames.get(i).getName()))
          return _attributeValues.get(i);
      }
  
      return null;
    }
    
    /**
     * Adds a child node.
     */
    @Override
    public void addChild(JspNode node)
      throws JspParseException
    {
      node.setParent(this);
      
      if (node instanceof JspAttribute) {
        JspAttribute attr = (JspAttribute) node;
  
        QName name = attr.getName();
  
        addAttribute(name, attr);
  
        _hasJspAttribute = true;
  
        int i = 0;
        while (_children != null && i < _children.size()) {
          JspNode child = _children.get(i);
  
          if (child instanceof StaticText) {
            String text = ((StaticText) child).getText();
  
            if (isWhitespace(text))
              _children.remove(i);
            else
              throw child.error(L.l("tags using jsp:attribute must put body content in a jsp:body tag."));
          }
          else if (child instanceof JspBody)
            i++;
          else if (child instanceof JspAttribute)
            i++;
          else {
            throw child.error(L.l("tags using jsp:attribute must put body content in a jsp:body tag"));
          }
        }
      }
      else if (_hasJspAttribute && ! (node instanceof JspBody)) {
        throw node.error(L.l("tags using jsp:attribute must put body content in a jsp:body tag"));
      }
      else if (node instanceof StaticText) {
        StaticText text = (StaticText) node;
        String data = text.getText();
  
        boolean isXml = _gen.isXml();
        for (JspNode ptr = this; ptr != null; ptr = ptr.getParent()) {
          if (ptr instanceof JspRoot)
            isXml = true;
        }
  
        if (_children == null)
          _children = new ArrayList<JspNode>();
        
        for (int i = 0;
             i < data.length();
             i++) {
          if (! XmlChar.isWhitespace(data.charAt(i))) {
            _children.add(node);
            return;
          }
        }
  
        if (! isXml)
          _children.add(node);
      }
      else if (node instanceof JspBody && hasJspBody()) {
        throw node.error(L.l("tags may only have a single jsp:body tag"));
      }
      else {
        if (_children == null)
          _children = new ArrayList<JspNode>();
  
        _children.add(node);
      }
    }
  
    protected void addAttributeChild(JspAttribute attr)
    {
      if (_attrChildren == null)
        _attrChildren = new ArrayList<JspAttribute>();
  
      _attrChildren.add(attr);
    }
  
    private boolean hasJspBody()
    {
      if (_children == null)
        return false;
  
  