Package org.odftoolkit.odfdom.doc.table

Source Code of org.odftoolkit.odfdom.doc.table.OdfTableColumn

/************************************************************************
*
*  Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF licenses this file
*  to you under the Apache License, Version 2.0 (the
*  "License"); you may not use this file except in compliance
*  with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing,
*  software distributed under the License is distributed on an
*  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
*  KIND, either express or implied.  See the License for the
*  specific language governing permissions and limitations
*  under the License.
*
************************************************************************/
package org.odftoolkit.odfdom.doc.table;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.xpath.XPath;

import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;

import org.odftoolkit.odfdom.pkg.OdfFileDom;
import org.odftoolkit.odfdom.pkg.OdfName;
import org.odftoolkit.odfdom.pkg.OdfXMLFactory;
import org.odftoolkit.odfdom.doc.OdfDocument;
import org.odftoolkit.odfdom.dom.OdfDocumentNamespace;
import org.odftoolkit.odfdom.dom.element.table.TableTableColumnElement;
import org.odftoolkit.odfdom.dom.element.table.TableTableColumnGroupElement;
import org.odftoolkit.odfdom.dom.element.table.TableTableColumnsElement;
import org.odftoolkit.odfdom.dom.element.table.TableTableElement;
import org.odftoolkit.odfdom.dom.element.table.TableTableHeaderColumnsElement;
import org.odftoolkit.odfdom.dom.style.OdfStyleFamily;
import org.odftoolkit.odfdom.dom.style.props.OdfTableColumnProperties;
import org.odftoolkit.odfdom.incubator.doc.style.OdfStyle;
import org.odftoolkit.odfdom.type.PositiveLength;
import org.odftoolkit.odfdom.type.Length.Unit;
import org.w3c.dom.Node;

/**
* OdfTableColumn represents table column feature in ODF document.
* <p>
* OdfTableColumn provides methods to get table cells that belong to this table column.
*
* @deprecated As of release 0.8.8, replaced by {@link org.odftoolkit.simple.table.Column} in Simple API.
*/
public class OdfTableColumn {

  TableTableColumnElement maColumnElement;
  int mnRepeatedIndex;
  private static final String DEFAULT_WIDTH = "0in";
  private OdfDocument mDocument;

  /**
   * Construct the <code>OdfTableColumn</code> feature.
   *
   * @param odfElement
   *           the element that can construct this table column
   * @param repeatedIndex
   *           the index in the repeated columns
   */
  OdfTableColumn(TableTableColumnElement colElement, int repeatedIndex) {
    maColumnElement = colElement;
    mnRepeatedIndex = repeatedIndex;
    mDocument = (OdfDocument) ((OdfFileDom) maColumnElement.getOwnerDocument()).getDocument();
  }

  /**
   * Get the <code>OdfTableColumn</code> instance from the <code>TableTableColumnElement</code> instance.
   * <p>
   * Each <code>TableTableColumnElement</code> instance has a one-to-one relationship to the a <code>OdfTableColumn</code> instance.
   *
   * @param colElement  the column element that need to get the corresponding <code>OdfTableColumn</code> instance
   * @return the <code>OdfTableColumn</code> instance represent the specified column element
   */
  public static OdfTableColumn getInstance(TableTableColumnElement colElement) {
    TableTableElement tableElement = null;
    Node node = colElement.getParentNode();
    while (node != null) {
      if (node instanceof TableTableElement) {
        tableElement = (TableTableElement) node;
      }
      node = node.getParentNode();
    }
    OdfTable table = null;
    if (tableElement != null) {
      table = OdfTable.getInstance(tableElement);
    } else {
      throw new IllegalArgumentException("the colElement is not in the table dom tree");
    }

    OdfTableColumn column = table.getColumnInstance(colElement, 0);
    if (column.getColumnsRepeatedNumber() > 1) {
      Logger.getLogger(OdfTableColumn.class.getName()).log(Level.WARNING, "the column has the repeated column number, and puzzled about get which repeated index of the column,"
          + "here just return the first column of the repeated columns.");
    }
    return column;
  }

  /**
   * Get the <code>TableTableElement</code> who contains this cell.
   * @return the table that contains the cell.
   */
  private TableTableElement getTableElement() {
    Node node = maColumnElement.getParentNode();
    while (node != null) {
      if (node instanceof TableTableElement) {
        return (TableTableElement) node;
      }
      node = node.getParentNode();
    }
    return null;
  }

  /**
   * Get owner table of the current column.
   *
   * @return
   *       the parent table of this column
   */
  public OdfTable getTable() {
    TableTableElement tableElement = getTableElement();
    if (tableElement != null) {
      return OdfTable.getInstance(tableElement);
    }
    return null;
  }

  /**
   * Get the width of the column (in Millimeter).
   *
   * @return the width of the current column (in Millimeter).
   */
  public long getWidth() {
    String sWidth = maColumnElement.getProperty(OdfTableColumnProperties.ColumnWidth);
    if (sWidth == null) {
      sWidth = DEFAULT_WIDTH;
    }
    return PositiveLength.parseLong(sWidth, Unit.MILLIMETER);
  }

  /**
   * Set the width of the column (in Millimeter).
   * @param width
   *         the width that will be set to the column (in Millimeter).
   */
  public void setWidth(long width) {
    String sWidthMM = String.valueOf(width) + Unit.MILLIMETER.abbr();
    String sWidthIN = PositiveLength.mapToUnit(sWidthMM, Unit.INCH);

    splitRepeatedColumns();
    maColumnElement.setProperty(OdfTableColumnProperties.ColumnWidth, sWidthIN);

    //check if need set relative width
    int index = getColumnIndex();
    if (index >= 1) {
      index = index - 1;
    } else {
      index = index + 1;
    }
    OdfTableColumn column = null;
    if (index < getTable().getColumnCount()) {
      column = getTable().getColumnByIndex(index);
    }
    if (column != null) {
      long prevColumnRelWidth = column.getRelativeWidth();
      if (prevColumnRelWidth != 0) {
        long prevColumnWidth = column.getWidth();
        setRelativeWidth(prevColumnRelWidth / prevColumnWidth * width);
      }
    }
  }

  //if one of the repeated column want to change something
  //then this repeated column have to split to repeated number columns
  //the maColumnElement should also be updated according to the original index in the repeated column
  void splitRepeatedColumns() {
    OdfTable table = getTable();
    TableTableElement tableEle = table.getOdfElement();
    int repeateNum = getColumnsRepeatedNumber();
    if (repeateNum > 1) {
      //change this repeated column to several single columns
      TableTableColumnElement ownerColumnElement = null;
      int repeatedColumnIndex = mnRepeatedIndex;
      Node refElement = maColumnElement;
      maColumnElement.removeAttributeNS(OdfDocumentNamespace.TABLE.getUri(), "number-columns-repeated");
      String originalWidth = maColumnElement.getProperty(OdfTableColumnProperties.ColumnWidth);
      String originalRelWidth = maColumnElement.getProperty(OdfTableColumnProperties.RelColumnWidth);
      for (int i = repeateNum - 1; i >= 0; i--) {
        TableTableColumnElement newColumn = (TableTableColumnElement) OdfXMLFactory.newOdfElement((OdfFileDom) maColumnElement.getOwnerDocument(),
            OdfName.newName(OdfDocumentNamespace.TABLE, "table-column"));
        if (originalWidth != null && originalWidth.length() > 0) {
          newColumn.setProperty(OdfTableColumnProperties.ColumnWidth, originalWidth);
        }
        if (originalRelWidth != null && originalRelWidth.length() > 0) {
          newColumn.setProperty(OdfTableColumnProperties.RelColumnWidth, originalRelWidth);
        }
        tableEle.insertBefore(newColumn, refElement);
        refElement = newColumn;
        if (repeatedColumnIndex == i) {
          ownerColumnElement = newColumn;
        } else {
          table.updateColumnRepository(maColumnElement, i, newColumn, 0);
        }
      }
      //remove this column element
      tableEle.removeChild(maColumnElement);

      if (ownerColumnElement != null) {
        table.updateColumnRepository(maColumnElement, mnRepeatedIndex, ownerColumnElement, 0);
      }
    }
  }

  private long getRelativeWidth() {
    String sRelWidth = maColumnElement.getProperty(OdfTableColumnProperties.RelColumnWidth);
    if (sRelWidth != null) {
      if (sRelWidth.contains("*")) {
        Long value = Long.valueOf(sRelWidth.substring(0, sRelWidth.indexOf("*")));
        return value.longValue();
      }
    }
    return 0;
  }

  private void setRelativeWidth(long relWidth) {
    maColumnElement.setProperty(OdfTableColumnProperties.RelColumnWidth, String.valueOf(relWidth) + "*");
  }

  /**
   * Returns if the column always keeps its optimal width.
   * @return
   *       true if the column always keeps its optimal width;
   *       vice versa
   */
  public boolean isOptimalWidth() {
    return Boolean.parseBoolean(maColumnElement.getProperty(OdfTableColumnProperties.UseOptimalColumnWidth));
  }

  /**
   * Set if the column always keeps its optimal width.
   *
   * @param isUseOptimalWidth
   *           the flag that indicate column should keep its optimal width or not
   */
  public void setUseOptimalWidth(boolean isUseOptimalWidth) {
    maColumnElement.setProperty(OdfTableColumnProperties.UseOptimalColumnWidth, String.valueOf(isUseOptimalWidth));
  }

  /**
   * Return an instance of <code>TableTableColumnElement</code> which represents this feature.
   *
   * @return an instance of <code>TableTableColumnElement</code>
   */
  public TableTableColumnElement getOdfElement() {
    return maColumnElement;
  }

  /**
   * Get the count of cells in this column.
   *
   * @return   the cells count in the current column
   */
  public int getCellCount() {
    return getTable().getRowCount();
  }

  /**
   * Get a cell with a specific index. The table will be automatically
   * expanded, when the given index is outside of the original table.
   *
   * @param index
   *            the cell index in this column
   * @return the cell object in the given cell index
   */
  public OdfTableCell getCellByIndex(int index) {
    return getTable().getCellByPosition(getColumnIndex(), index);
  }

  /**
   * Get the previous column of the current column.
   *
   * @return the previous column before this column in the owner table
   */
  public OdfTableColumn getPreviousColumn() {
    OdfTable table = getTable();
    //the column has repeated column number > 1
    if (maColumnElement.getTableNumberColumnsRepeatedAttribute().intValue() > 1) {
      if (mnRepeatedIndex > 0) {
        return table.getColumnInstance(maColumnElement, mnRepeatedIndex - 1);
      }
    }
    //the column has repeated column number > 1 && the index is 0
    //or the column has repeated column num = 1
    Node aPrevNode = maColumnElement.getPreviousSibling();
    Node aCurNode = maColumnElement;
    while (true) {
      if (aPrevNode == null) {
        //does not have previous sibling, then get the parent
        //because aCurNode might be the child element of table-header-columns, table-columns, table-column-group
        Node parentNode = aCurNode.getParentNode();
        //if the parent is table, then it means that this column is the first column in this table
        //it has no previous column
        if (parentNode instanceof TableTableElement) {
          return null;
        }
        aPrevNode = parentNode.getPreviousSibling();
      }
      //else the parent node might be table-header-columns, table-columns, table-column-group
      if (aPrevNode != null) {
        try {
          if (aPrevNode instanceof TableTableColumnElement) {
            return table.getColumnInstance((TableTableColumnElement) aPrevNode, ((TableTableColumnElement) aPrevNode).getTableNumberColumnsRepeatedAttribute().intValue() - 1);
          } else if (aPrevNode instanceof TableTableColumnsElement
              || aPrevNode instanceof TableTableHeaderColumnsElement
              || aPrevNode instanceof TableTableColumnGroupElement) {
            XPath xpath = ((OdfFileDom) maColumnElement.getOwnerDocument()).getXPath();
            TableTableColumnElement lastCol = (TableTableColumnElement) xpath.evaluate("//table:table-column[last()]", aPrevNode, XPathConstants.NODE);
            if (lastCol != null) {
              return table.getColumnInstance(lastCol, lastCol.getTableNumberColumnsRepeatedAttribute().intValue() - 1);
            }
          } else {
            aCurNode = aPrevNode;
            aPrevNode = aPrevNode.getPreviousSibling();
          }
        } catch (XPathExpressionException e) {
          Logger.getLogger(OdfTableColumn.class.getName()).log(Level.SEVERE, e.getMessage(), e);
        }
      }
    }
  }

  /**
   * Get the next column of the current column.
   *
   * @return the next column after this column in the owner table
   */
  public OdfTableColumn getNextColumn() {
    OdfTable table = getTable();
    //the column has repeated column number > 1
    if (getColumnsRepeatedNumber() > 1) {
      if (mnRepeatedIndex < (getColumnsRepeatedNumber() - 1)) {
        return table.getColumnInstance(maColumnElement, mnRepeatedIndex + 1);
      }
    }
    Node aNextNode = maColumnElement.getNextSibling();
    Node aCurNode = maColumnElement;
    while (true) {
      if (aNextNode == null) {
        //does not have next sibling, then get the parent
        //because aCurNode might be the child element of table-header-columns, table-columns, table-column-group
        Node parentNode = aCurNode.getParentNode();
        //if the parent is table, then it means that this column is the last column in this table
        //it has no next column
        if (parentNode instanceof TableTableElement) {
          return null;
        }
        aNextNode = parentNode.getNextSibling();
      }
      //else the parent node might be table-header-columns, table-columns, table-column-group
      if (aNextNode != null) {
        try {
          if (aNextNode instanceof TableTableColumnElement) {
            return table.getColumnInstance((TableTableColumnElement) aNextNode, 0);
          } else if (aNextNode instanceof TableTableColumnsElement
              || aNextNode instanceof TableTableHeaderColumnsElement
              || aNextNode instanceof TableTableColumnGroupElement) {
            XPath xpath = ((OdfFileDom) maColumnElement.getOwnerDocument()).getXPath();
            TableTableColumnElement firstCol = (TableTableColumnElement) xpath.evaluate("//table:table-column[first()]", aNextNode, XPathConstants.NODE);
            if (firstCol != null) {
              return table.getColumnInstance(firstCol, 0);
            }
          } else {
            aCurNode = aNextNode;
            aNextNode = aNextNode.getNextSibling();
          }
        } catch (XPathExpressionException e) {
          Logger.getLogger(OdfTableColumn.class.getName()).log(Level.SEVERE, e.getMessage(), e);
        }
      }
    }
  }

  /**
   * Get the index of this column in the owner table.
   *
   * @return the index of the column
   */
  public int getColumnIndex() {
    int result = 0;
    OdfTable table = getTable();
    TableTableColumnElement columnEle;
    TableTableElement mTableElement = table.getOdfElement();
    for (Node n : new DomNodeList(mTableElement.getChildNodes())) {
      if (n instanceof TableTableHeaderColumnsElement) {
        TableTableHeaderColumnsElement headers = (TableTableHeaderColumnsElement) n;
        for (Node m : new DomNodeList(headers.getChildNodes())) {
          if (m instanceof TableTableColumnElement) {
            columnEle = (TableTableColumnElement) m;
            if (columnEle == getOdfElement()) {
              return result + mnRepeatedIndex;
            }
            if (columnEle.getTableNumberColumnsRepeatedAttribute() == null) {
              result += 1;
            } else {
              result += columnEle.getTableNumberColumnsRepeatedAttribute();
            }
          }
        }
      }
      if (n instanceof TableTableColumnElement) {
        columnEle = (TableTableColumnElement) n;
        if (columnEle == getOdfElement()) {
          break;
        }
        if (columnEle.getTableNumberColumnsRepeatedAttribute() == null) {
          result += 1;
        } else {
          result += columnEle.getTableNumberColumnsRepeatedAttribute();
        }
      }
    }
    return result + mnRepeatedIndex;
  }

  /**
   * Set the default cell style to this column.
   * <p>
   * The style should already exist in this document.
   * <p>
   * This method is not recommended for text document cases.
   * These is a style assigned to each cell in tables under text documents.
   * So setting the default cell style to a column may not work.
   *
   * @param style
   *       the cell style of the document
   */
  public void setDefaultCellStyle(OdfStyle style) {
    splitRepeatedColumns();
    OdfStyle defaultStyle = getDefaultCellStyle();
    if (defaultStyle != null) {
      defaultStyle.removeStyleUser(maColumnElement);
    }

    if (style != null) {
      style.addStyleUser(maColumnElement);
      maColumnElement.setTableDefaultCellStyleNameAttribute(
          style.getStyleNameAttribute());
    }
  }

  /**
   * Get the default cell style of this column.
   * @return the default cell style of this column
   */
  public OdfStyle getDefaultCellStyle() {
    String styleName = maColumnElement.getTableDefaultCellStyleNameAttribute();
    OdfStyle style = maColumnElement.getAutomaticStyles().getStyle(
        styleName, OdfStyleFamily.TableCell);

    if (style == null) {
      style = mDocument.getDocumentStyles().getStyle(styleName, OdfStyleFamily.TableCell);
    }
    return style;
  }

  //note: we have to use this method to modify the column repeated number
  //in order to update mnRepeatedIndex of the each column
  void setColumnsRepeatedNumber(int num) {
    //update the mnRepeatedIndex for the ever repeated column
    maColumnElement.setTableNumberColumnsRepeatedAttribute(Integer.valueOf(num));
  }

  int getColumnsRepeatedNumber() {
    Integer count = maColumnElement.getTableNumberColumnsRepeatedAttribute();
    if (count == null) {
      return 1;
    } else {
      return count.intValue();
    }
  }
}
TOP

Related Classes of org.odftoolkit.odfdom.doc.table.OdfTableColumn

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.