/**
   * This method traverses <i>office:settings</i> {@code Element}.
   *
   * @param node <i>office:settings</i> {@code Node}.
   * @throws IOException If any I/O error occurs.
   */
  public void traverseSettings(Node node) throws IOException {
    if (node.hasChildNodes()) {

      NodeList nodeList = node.getChildNodes();
      int len = nodeList.getLength();
      for (int i = 0; i < len; i++) {
        Node child = nodeList.item(i);

        if (child.getNodeType() == Node.ELEMENT_NODE) {
          String nodeName = child.getNodeName();

          if (nodeName.equals(TAG_CONFIG_ITEM_SET)) {

            traverseSettings(child);

          } else if (nodeName.equals(TAG_CONFIG_ITEM_MAP_INDEXED)) {

            traverseSettings(child);

          } else if (nodeName.equals(TAG_CONFIG_ITEM_MAP_ENTRY)) {

            BookSettings bs = new BookSettings(child);
            encoder.addSettings(bs);

          } else {

            Debug.log(Debug.TRACE, "<OTHERS " + XmlUtil.getNodeInfo(child) + " />");
          }
        }
      }
    }
  }
  /**
   * This method traverses <i>office:body</i> {@code Element}.
   *
   * @param node <i>office:body</i> {@code Node}.
   * @throws IOException If any I/O error occurs.
   */
  protected void traverseBody(Node node) throws IOException {

    Debug.log(Debug.TRACE, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    Debug.log(Debug.TRACE, "<DEBUGLOG>");

    if (node.hasChildNodes()) {

      NodeList nodeList = node.getChildNodes();
      int len = nodeList.getLength();

      for (int i = 0; i < len; i++) {
        Node searchNode = nodeList.item(i);
        if (searchNode.getNodeType() == Node.ELEMENT_NODE) {

          String nodeName = searchNode.getNodeName();

          if (nodeName.equals(TAG_NAMED_EXPRESSIONS)) {

            traverseNamedExpressions(searchNode);

          } else {

            Debug.log(Debug.TRACE, "Skipping " + XmlUtil.getNodeInfo(searchNode) + " />");
          }
        }
      }

      for (int i = 0; i < len; i++) {
        Node child = nodeList.item(i);

        if (child.getNodeType() == Node.ELEMENT_NODE) {
          String nodeName = child.getNodeName();

          if (nodeName.equals(TAG_TABLE)) {

            traverseTable(child);

          } else {

            Debug.log(Debug.TRACE, "<OTHERS " + XmlUtil.getNodeInfo(child) + " />");
          }
        }
      }
    }

    Debug.log(Debug.TRACE, "</DEBUGLOG>");
  }
  /**
   * This method traverses the <i>table:table</i> element {@code Node}.
   *
   * @param node A <i>table:table</i> {@code Node}.
   * @throws IOException If any I/O error occurs.
   */
  protected void traverseTable(Node node) throws IOException {

    Debug.log(Debug.TRACE, "<TABLE>");

    ColumnRowList = new ArrayList<ColumnRowInfo>();

    // Get table attributes
    // ToDo - extract style from attribute

    NamedNodeMap att = node.getAttributes();

    String tableName = att.getNamedItem(ATTRIBUTE_TABLE_NAME).getNodeValue();

    rowID = 1;

    encoder.createWorksheet(tableName);

    if (node.hasChildNodes()) {

      NodeList nodeList = node.getChildNodes();
      int len = nodeList.getLength();

      for (int i = 0; i < len; i++) {
        Node child = nodeList.item(i);

        if (child.getNodeType() == Node.ELEMENT_NODE) {
          String nodeName = child.getNodeName();

          if (nodeName.equals(TAG_TABLE_ROW)) {
            // TODO - handle all the possible rows
            // spelled out in the entities

            traverseTableRow(child);

          } else if (nodeName.equals(TAG_TABLE_COLUMN)) {

            traverseTableColumn(child);

          } else if (nodeName.equals(TAG_TABLE_SCENARIO)) {

            // TODO

          } else {

            Debug.log(Debug.TRACE, "<OTHERS " + XmlUtil.getNodeInfo(child) + " />");
          }
        }
      }
    }

    // Add column width info to the current sheet
    encoder.setColumnRows(ColumnRowList);

    Debug.log(Debug.TRACE, "</TABLE>");
  }
  /**
   * This method traverses the <i>table:table-row</i> element {@code Node}.
   *
   * @param node A <i>table:table-row</i> {@code Node}.
   * @throws IOException If any I/O error occurs.
   */
  protected void traverseTableRow(Node node) throws IOException {

    // Get the attributes of the row
    NamedNodeMap cellAtt = node.getAttributes();

    if (cellAtt != null) {

      Node rowStyle = cellAtt.getNamedItem(ATTRIBUTE_TABLE_STYLE_NAME);

      Node tableNumRowRepeatingNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_NUM_ROWS_REPEATED);
      int repeatedRows = 1;

      if (tableNumRowRepeatingNode != null) {
        String repeatStr = tableNumRowRepeatingNode.getNodeValue();
        Debug.log(Debug.TRACE, "traverseTableRow() repeated-rows : " + repeatStr);
        repeatedRows = Integer.parseInt(repeatStr);
      }

      String styleName = "";

      if (rowStyle != null) {
        styleName = rowStyle.getNodeValue();
      }
      if (styleName.equalsIgnoreCase("Default") || styleName.length() == 0) {

        Debug.log(Debug.TRACE, "No defined Row Style Attribute was found");

      } else {

        RowStyle rStyle =
            (RowStyle)
                styleCat.lookup(styleName, SxcConstants.ROW_STYLE_FAMILY, null, RowStyle.class);

        int rowHeight = rStyle != null ? rStyle.getRowHeight() : 0;

        Debug.log(Debug.TRACE, "traverseTableRow() Row Height : " + rowHeight);
        ColumnRowInfo ri =
            new ColumnRowInfo(rowHeight, repeatedRows, ColumnRowInfo.ROW, rowHeight != 0);
        ColumnRowList.add(ri);
      }

      // Get the attribute representing the number of rows repeated
      Node rowsRepeatedNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_NUM_ROWS_REPEATED);

      // There is a number of rows repeated attribute:
      if (rowsRepeatedNode != null) {
        // Get the number of times the row is repeated
        String rowsRepeatedString = rowsRepeatedNode.getNodeValue();
        rowsRepeated = Integer.parseInt(rowsRepeatedString);
      } else {
        // The row is not repeated
        rowsRepeated = 1;
      }
    }

    Debug.log(Debug.TRACE, "<TR>");

    if (node.hasChildNodes()) {

      NodeList nodeList = node.getChildNodes();
      int len = nodeList.getLength();

      for (int i = 0; i < len; i++) {
        Node child = nodeList.item(i);

        if (child.getNodeType() == Node.ELEMENT_NODE) {
          String nodeName = child.getNodeName();

          if (nodeName.equals(TAG_TABLE_CELL)) {

            traverseCell(child);

          } else {

            Debug.log(Debug.TRACE, "<OTHERS " + XmlUtil.getNodeInfo(child) + " />");
          }
        }
      }
    }

    // Increase the row counter by the number of rows which are repeated
    rowID += rowsRepeated;

    // Re-initialize number of rows repeated before processing the next
    // row data.
    rowsRepeated = 1;

    // When starting a new row, set the column counter back to the
    // first column.
    colID = 1;

    // Re-initialize number of columns repeated before processing
    // the next row data.
    colsRepeated = 1;

    Debug.log(Debug.TRACE, "</TR>");
  }