/**
   * * Transforms the contents of a given cell from the POI-model to a {@link Formula} and sets the
   * formula as content of the given cell from the internal model.
   *
   * @param cell The given cell from the internal model.
   * @param poiCell The given cell form the POI-model.
   */
  protected void transformFormulaContent(Cell cell, org.apache.poi.ss.usermodel.Cell poiCell) {

    // Create formula and add to cell.
    Formula formula = new Formula();
    cell.setFormula(formula);
    formula.setCell(cell);
    formula.setFormulaString(poiCell.getCellFormula());

    // Set formula result type.
    switch (poiCell.getCachedFormulaResultType()) {
      case org.apache.poi.ss.usermodel.Cell.CELL_TYPE_NUMERIC:
        formula.setResultType(CellContentType.NUMERIC);
        cell.setNumericContent(poiCell.getNumericCellValue());
        break;
      case org.apache.poi.ss.usermodel.Cell.CELL_TYPE_STRING:
        formula.setResultType(CellContentType.TEXT);
        cell.setTextContent(poiCell.getStringCellValue());
        break;
      case org.apache.poi.ss.usermodel.Cell.CELL_TYPE_BOOLEAN:
        formula.setResultType(CellContentType.BOOLEAN);
        cell.setBooleanContent(poiCell.getBooleanCellValue());
        break;
      case org.apache.poi.ss.usermodel.Cell.CELL_TYPE_ERROR:
        formula.setResultType(CellContentType.ERROR);
        cell.setErrorContent(FormulaError.forInt(poiCell.getErrorCellValue()).toString());
        break;
      default:
        break;
    }

    // Set formula content.
    Stack<Ptg> ptgs = getPtgStackFor(poiCell);
    transform(cell, ptgs, formula, ptgs.size());
  }
  /**
   * * Transforms a given OperandPtg to its correspondent in the internal model.
   *
   * @param ptg The given OperandPtg
   * @return The correspondent of the given OperandPtg in the internal model.
   */
  private AbstractReference transform(Cell cell, OperandPtg ptg) {
    AbstractReference reference = null;
    // Cell-Reference.
    if (ptg instanceof RefPtgBase) {
      RefPtgBase refPtgBase = (RefPtgBase) ptg;

      // Create new cell reference.
      CellReference cellReference = new CellReference();
      reference = cellReference;

      // Create referenced address.
      CellAddress referencedCellAddress = new CellAddress();
      referencedCellAddress.setColumnIndex(refPtgBase.getColumn() + 1);
      referencedCellAddress.setRowIndex(refPtgBase.getRow() + 1);
      referencedCellAddress.setWorksheet(cell.getWorksheet());

      // Cell reference is within worksheet.
      if (ptg instanceof RefPtg) {
        referencedCellAddress.setWorksheet(cell.getWorksheet());
      }
      // Cell reference is to a different worksheet.
      if (refPtgBase instanceof Ref3DPtg) {
        Ref3DPtg ref3DPtg = (Ref3DPtg) refPtgBase;
        Workbook poiWorkbook = poiIO.poiWorkbook;
        Integer sheetIndex = null;

        // Get the sheet index.
        if (poiWorkbook instanceof HSSFWorkbook) {
          sheetIndex =
              ((HSSFWorkbook) poiWorkbook)
                  .getSheetIndexFromExternSheetIndex(ref3DPtg.getExternSheetIndex());
        } else {
          sheetIndex = ref3DPtg.getExternSheetIndex();
        }

        // Transform sheet index to a 1 based index.
        referencedCellAddress.setWorksheet(poiIO.spreadsheet.getWorksheetAt(sheetIndex + 1));
      }

      // Get referenced cell.
      Cell referencedCell = poiIO.spreadsheet.getCellFor(referencedCellAddress);

      // Create blank cell if referenced cell does not exist.
      if (referencedCell == null) {
        referencedCell = new Cell();
        referencedCell.setColumnIndex(referencedCellAddress.getColumnIndex());
        referencedCell.setRowIndex(referencedCellAddress.getRowIndex());
        Worksheet worksheet = referencedCellAddress.getWorksheet();
        referencedCell.setWorksheet(worksheet);
        worksheet.add(referencedCell);
      }

      // Set up cell reference.
      cellReference.setColumnRelative(refPtgBase.isColRelative());
      cellReference.setRowRelative(refPtgBase.isRowRelative());
      cellReference.setReferencedElement(referencedCell);
      cellReference.setReferencingElement(cell);
    }

    // Range-Reference.
    if (ptg instanceof AreaPtgBase) {
      AreaPtgBase areaPtgBase = (AreaPtgBase) ptg;

      // Create new range reference.
      RangeReference rangeReference = new RangeReference();
      reference = rangeReference;

      // Create address.
      RangeAddress referencedRangeAddress = new RangeAddress();
      referencedRangeAddress.setLeftmostColumnIndex(areaPtgBase.getFirstColumn() + 1);
      referencedRangeAddress.setTopmostRowIndex(areaPtgBase.getFirstRow() + 1);
      referencedRangeAddress.setRightmostColumnIndex(areaPtgBase.getLastColumn() + 1);
      referencedRangeAddress.setBottommostRowIndex(areaPtgBase.getLastRow() + 1);
      referencedRangeAddress.setWorksheet(cell.getWorksheet());
      // Reference is within worksheet.
      if (areaPtgBase instanceof AreaPtg) {
        referencedRangeAddress.setWorksheet(cell.getWorksheet());
      }
      // Reference is to a different worksheet.
      if (areaPtgBase instanceof Area3DPtg) {
        Area3DPtg area3DPtg = (Area3DPtg) areaPtgBase;
        referencedRangeAddress.setWorksheet(
            poiIO.spreadsheet.getWorksheetAt(area3DPtg.getExternSheetIndex() + 1));
      }

      // Create blank cells if needed.
      poiIO.spreadsheet.createBlankCellsForNullCellsIn(referencedRangeAddress);

      // Get referenced range.
      Range referencedRange = poiIO.spreadsheet.getRangeFor(referencedRangeAddress);

      // Set up range reference.
      rangeReference.setReferencedElement(referencedRange);
      rangeReference.setReferencingElement(cell);

      rangeReference.setLeftmostColumnRelative(areaPtgBase.isFirstColRelative());
      rangeReference.setTopmostRowRelative(areaPtgBase.isFirstRowRelative());
      rangeReference.setRightmostColumnRelative(areaPtgBase.isLastColRelative());
      rangeReference.setBottommostRowRelative(areaPtgBase.isLastRowRelative());
    }

    return reference;
  }