/**
   * This method traverses a <i>table:table-cell</i> element {@code Node}.
   *
   * @param node a <i>table:table-cell</i> {@code Node}.
   * @throws IOException if any I/O error occurs.
   */
  protected void traverseCell(Node node) throws IOException {

    NamedNodeMap cellAtt = node.getAttributes();

    fmt.clearFormatting();

    // Get the type of data in the cell
    Node tableValueTypeNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_VALUE_TYPE);

    // Get the number of columns this cell is repeated
    Node colsRepeatedNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED);

    // Get the style type
    Node tableStyleNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_STYLE_NAME);

    String styleName = "";

    if (tableStyleNode != null) {
      styleName = tableStyleNode.getNodeValue();
    }

    CellStyle cStyle = null;

    if (styleName.equalsIgnoreCase("Default")) {

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

    } else if (styleName.length() != 0) {

      cStyle =
          (CellStyle)
              styleCat.lookup(
                  styleName, SxcConstants.TABLE_CELL_STYLE_FAMILY, null, CellStyle.class);
    }

    if (cStyle != null) {
      Format definedFormat = cStyle.getFormat();
      fmt = new Format(definedFormat);
    }

    // There is a number of cols repeated attribute
    if (colsRepeatedNode != null) {
      // Get the number of times the cell is repeated
      String colsRepeatedString = colsRepeatedNode.getNodeValue();
      colsRepeated = Integer.parseInt(colsRepeatedString);
    } else {
      // The cell is not repeated
      colsRepeated = 1;
    }

    // if there is no style we need to check to see if there is a default
    // cell style defined in the table-column's

    if (fmt.isDefault() && styleName.length() == 0) {
      int index = 1;
      for (Iterator<ColumnRowInfo> e = ColumnRowList.iterator(); e.hasNext(); ) {
        ColumnRowInfo cri = e.next();
        if (cri.isColumn()) {
          if (colID >= index && colID < (index + cri.getRepeated())) {
            fmt = new Format(cri.getFormat());
          }
          index += cri.getRepeated();
        }
      }
    }

    if (tableValueTypeNode != null) {

      String cellType = tableValueTypeNode.getNodeValue();

      if (cellType.equalsIgnoreCase(CELLTYPE_STRING)) {

        // has text:p tag
        fmt.setCategory(CELLTYPE_STRING);
        Node tableStringValueNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_STRING_VALUE);
        Debug.log(Debug.TRACE, "Cell Type String :  " + tableStringValueNode);
        if (tableStringValueNode != null) {
          fmt.setValue(tableStringValueNode.getNodeValue());
        }

      } else if (cellType.equalsIgnoreCase(CELLTYPE_FLOAT)) {

        // has table:value attribute
        // has text:p tag

        // Determine the number of decimal places StarCalc
        // is displaying for this floating point output.
        fmt.setCategory(CELLTYPE_FLOAT);
        fmt.setDecimalPlaces(getDecimalPlaces(node));
        Node tableValueNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_VALUE);
        fmt.setValue(tableValueNode.getNodeValue());

      } else if (cellType.equalsIgnoreCase(CELLTYPE_TIME)) {

        // has table:time-value attribute
        // has text:p tag - which is the value we convert

        fmt.setCategory(CELLTYPE_TIME);
        Node tableTimeNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_TIME_VALUE);
        fmt.setValue(tableTimeNode.getNodeValue());

      } else if (cellType.equalsIgnoreCase(CELLTYPE_DATE)) {

        // has table:date-value attribute
        // has text:p tag - which is the value we convert

        fmt.setCategory(CELLTYPE_DATE);
        Node tableDateNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_DATE_VALUE);
        fmt.setValue(tableDateNode.getNodeValue());

      } else if (cellType.equalsIgnoreCase(CELLTYPE_CURRENCY)) {

        // has table:currency
        // has table:value attribute
        // has text:p tag

        fmt.setCategory(CELLTYPE_CURRENCY);
        fmt.setDecimalPlaces(getDecimalPlaces(node));
        Node tableValueNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_VALUE);
        fmt.setValue(tableValueNode.getNodeValue());

      } else if (cellType.equalsIgnoreCase(CELLTYPE_BOOLEAN)) {

        // has table:boolean-value attribute
        // has text:p tag - which is the value we convert

        fmt.setCategory(CELLTYPE_BOOLEAN);
        Node tableBooleanNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_BOOLEAN_VALUE);
        fmt.setValue(tableBooleanNode.getNodeValue());

      } else if (cellType.equalsIgnoreCase(CELLTYPE_PERCENT)) {

        // has table:value attribute
        // has text:p tag

        fmt.setCategory(CELLTYPE_PERCENT);
        fmt.setDecimalPlaces(getDecimalPlaces(node));
        Node tableValueNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_VALUE);
        fmt.setValue(tableValueNode.getNodeValue());

      } else {

        Debug.log(Debug.TRACE, "No defined value type" + cellType);
        // Should never get here

      }
    }

    Node tableFormulaNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_FORMULA);

    if (tableFormulaNode != null) {
      if (tableValueTypeNode
          == null) { // If there is no value-type Node we must assume string-value
        fmt.setCategory(CELLTYPE_STRING);
        Node tableStringValueNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_STRING_VALUE);
        fmt.setValue(tableStringValueNode.getNodeValue());
      }
      String cellFormula = tableFormulaNode.getNodeValue();
      addCell(cellFormula);
    } else {

      // Text node, Date node, or Time node

      Debug.log(Debug.INFO, "TextNode, DateNode, TimeNode or BooleanNode\n");
      // This handles the case where we have style information but no content
      if (node.hasChildNodes()) {
        NodeList childList = node.getChildNodes();
        int len = childList.getLength();

        for (int i = 0; i < len; i++) {
          Node child = childList.item(i);
          if (child.getNodeType() == Node.ELEMENT_NODE) {
            String childName = child.getNodeName();
            if (childName.equals(TAG_PARAGRAPH)) {
              traverseParagraph(child);
            }
          }
        }
      } else if (!fmt.isDefault()) {
        addCell("");
      }
    }

    // Increase the column counter by the number of times the
    // last cell was repeated.
    colID += colsRepeated;

    // Re-initialize the number of columns repeated before processing
    // the next cell data.
    colsRepeated = 1;
  }
  /**
   * This method traverses the <i>table:table-column</i> {@code Node}.
   *
   * <p>Not yet implemented.
   *
   * @param node A <i>table:table-column</i> {@code Node}.
   * @throws IOException If any I/O error occurs.
   */
  protected void traverseTableColumn(Node node) throws IOException {

    Debug.log(Debug.TRACE, "traverseColumn() : ");
    NamedNodeMap cellAtt = node.getAttributes();
    Node tableStyleNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_STYLE_NAME);
    Node tableNumColRepeatingNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED);
    Node tableDefaultCellStyle = cellAtt.getNamedItem(ATTRIBUTE_DEFAULT_CELL_STYLE);

    int repeatedColumns = 1;
    int columnWidth = 0;
    ColumnRowInfo col = new ColumnRowInfo(ColumnRowInfo.COLUMN);

    if (tableNumColRepeatingNode != null) {
      Debug.log(
          Debug.TRACE,
          "traverseColumn() repeated-cols : " + tableNumColRepeatingNode.getNodeValue());
      repeatedColumns = Integer.parseInt(tableNumColRepeatingNode.getNodeValue());
      col.setRepeated(repeatedColumns);
    }

    String cellStyleName = "";

    if (tableDefaultCellStyle != null) {
      cellStyleName = tableDefaultCellStyle.getNodeValue();

      Debug.log(Debug.TRACE, "traverseColumn() default-cell-style : " + cellStyleName);
    }

    CellStyle cellStyle = null;

    if (cellStyleName.equalsIgnoreCase("Default") || cellStyleName.length() == 0) {

      Debug.log(Debug.TRACE, "No default cell Style Attribute was found");

    } else {

      cellStyle =
          (CellStyle)
              styleCat.lookup(
                  cellStyleName, SxcConstants.TABLE_CELL_STYLE_FAMILY, null, CellStyle.class);
    }

    if (cellStyle != null) {
      Format defaultFmt = new Format(cellStyle.getFormat());
      col.setFormat(defaultFmt);
    }

    String styleName = "";

    if (tableStyleNode != null) {
      styleName = tableStyleNode.getNodeValue();
    }

    if (styleName.equalsIgnoreCase("Default") || styleName.length() == 0) {

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

    } else {

      ColumnStyle cStyle =
          (ColumnStyle)
              styleCat.lookup(styleName, SxcConstants.COLUMN_STYLE_FAMILY, null, ColumnStyle.class);

      columnWidth = cStyle != null ? cStyle.getColWidth() : 0;
      col.setSize(columnWidth);
      Debug.log(Debug.TRACE, "traverseColumn() Column Width : " + columnWidth);
    }
    ColumnRowList.add(col);
  }