/**
   * Generates specific XML (sometimes called 'attribute-oriented XML'). Like this:
   *
   * <pre>
   * &lt;Join condition="EMP.DEPTNO = DEPT.DEPTNO"&gt;
   *   &lt;Project expr1="x + y" expr2="42"&gt;
   *   &lt;TableAccess table="SALES.EMPS"&gt;
   * &lt;/Join&gt;
   * </pre>
   *
   * @param rel Relational expression
   * @param terms Names of the attributes of the plan
   * @param values Values of the attributes of the plan
   */
  private void explainSpecific(RelNode rel, String[] terms, Object[] values) {
    RelNode[] inputs = rel.getInputs();
    RexNode[] children = rel.getChildExps();
    assert terms.length == (inputs.length + children.length + values.length)
        : "terms.length="
            + terms.length
            + " inputs.length="
            + inputs.length
            + " children.length="
            + children.length
            + " values.length="
            + values.length;
    String tagName = rel.getRelTypeName();
    xmlOutput.beginBeginTag(tagName);
    xmlOutput.attribute("id", rel.getId() + "");

    int j = 0;
    for (int i = 0; i < children.length; i++) {
      RexNode child = children[i];
      xmlOutput.attribute(terms[inputs.length + j++], child.toString());
    }
    for (int i = 0; i < values.length; i++) {
      Object value = values[i];
      if (value != null) {
        xmlOutput.attribute(terms[inputs.length + j++], value.toString());
      }
    }
    xmlOutput.endBeginTag(tagName);
    level++;
    for (int i = 0; i < inputs.length; i++) {
      RelNode child = inputs[i];
      child.explain(this);
    }
    level--;
  }
  /**
   * Generates generic XML (sometimes called 'element-oriented XML'). Like this:
   *
   * <blockquote>
   *
   * <code>
   * &lt;RelNode id="1" type="Join"&gt;<br/>
   * &nbsp;&nbsp;&lt;Property name="condition"&gt;EMP.DEPTNO =
   * DEPT.DEPTNO&lt;/Property&gt;<br/>
   * &nbsp;&nbsp;&lt;Inputs&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&lt;RelNode id="2" type="Project"&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Property name="expr1"&gt;x +
   * y&lt;/Property&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Property
   * name="expr2"&gt;45&lt;/Property&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&lt;/RelNode&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&lt;RelNode id="3" type="TableAccess"&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Property
   * name="table"&gt;SALES.EMP&lt;/Property&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&lt;/RelNode&gt;<br/>
   * &nbsp;&nbsp;&lt;/Inputs&gt;<br/>
   * &lt;/RelNode&gt;<br/>
   * </code>
   *
   * </blockquote>
   *
   * @param rel Relational expression
   * @param terms Names of the attributes of the plan
   * @param values Values of the attributes of the plan
   */
  private void explainGeneric(RelNode rel, String[] terms, Object[] values) {
    RelNode[] inputs = rel.getInputs();
    RexNode[] children = rel.getChildExps();
    assert terms.length == (inputs.length + children.length + values.length)
        : "terms.length="
            + terms.length
            + " inputs.length="
            + inputs.length
            + " children.length="
            + children.length
            + " values.length="
            + values.length;
    String relType = rel.getRelTypeName();
    xmlOutput.beginBeginTag("RelNode");
    xmlOutput.attribute("type", relType);

    // xmlOutput.attribute("id", rel.getId() + "");
    xmlOutput.endBeginTag("RelNode");

    int j = 0;
    for (int i = 0; i < children.length; i++) {
      RexNode child = children[i];
      xmlOutput.beginBeginTag("Property");
      xmlOutput.attribute("name", terms[inputs.length + j++]);
      xmlOutput.endBeginTag("Property");
      xmlOutput.cdata(child.toString());
      xmlOutput.endTag("Property");
    }
    for (int i = 0; i < values.length; i++) {
      Object value = values[i];
      if (value != null) {
        xmlOutput.beginBeginTag("Property");
        xmlOutput.attribute("name", terms[inputs.length + j++]);
        xmlOutput.endBeginTag("Property");
        xmlOutput.cdata(value.toString());
        xmlOutput.endTag("Property");
      }
    }
    xmlOutput.beginTag("Inputs", null);
    level++;
    for (int i = 0; i < inputs.length; i++) {
      RelNode child = inputs[i];
      child.explain(this);
    }
    level--;
    xmlOutput.endTag("Inputs");
    xmlOutput.endTag("RelNode");
  }