/************************************************************** * * 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 ifc.sheet; import java.util.ArrayList; import com.sun.star.beans.XPropertySet; import com.sun.star.container.XIndexAccess; import com.sun.star.container.XNamed; import com.sun.star.lang.IllegalArgumentException; import com.sun.star.sheet.*; import com.sun.star.table.CellAddress; import com.sun.star.table.CellRangeAddress; import com.sun.star.table.XCell; import com.sun.star.table.XCellCursor; import com.sun.star.table.XCellRange; import com.sun.star.uno.AnyConverter; import com.sun.star.uno.UnoRuntime; import lib.MultiMethodTest; import lib.Status; import lib.StatusException; /** * Testing com.sun.star.sheet.XDataPilotTable2 * interface methods : * * * @see com.sun.star.sheet.XDataPilotTable2 * @see com.sun.star.table.CellAddress * */ public class _XDataPilotTable2 extends MultiMethodTest { private XSpreadsheetDocument xSheetDoc = null; private XDataPilotTable2 xDPTab2 = null; private CellRangeAddress mRangeWhole = null; private CellRangeAddress mRangeTable = null; private CellRangeAddress mRangeResult = null; private ArrayList mDataFieldDims = null; private ArrayList mResultCells = null; /** * exception to be thrown when obtaining a result data for a cell fails * (probably because the cell is not a result cell). */ private class ResultCellFailure extends com.sun.star.uno.Exception {} protected void before() { Object o = tEnv.getObjRelation("DATAPILOTTABLE2"); xDPTab2 = (XDataPilotTable2)UnoRuntime.queryInterface( XDataPilotTable2.class, o); if (xDPTab2 == null) throw new StatusException(Status.failed("Relation not found")); xSheetDoc = (XSpreadsheetDocument)tEnv.getObjRelation("SHEETDOCUMENT"); getOutputRanges(); buildDataFields(); try { buildResultCells(); } catch (ResultCellFailure e) { e.printStackTrace(log); throw new StatusException( "Failed to build result cells.", e); } } public void _getDrillDownData() { boolean testResult = true; int cellCount = mResultCells.size(); for (int i = 0; i < cellCount; ++i) { CellAddress addr = (CellAddress)mResultCells.get(i); DataPilotTablePositionData posData = xDPTab2.getPositionData(addr); DataPilotTableResultData resData = (DataPilotTableResultData)posData.PositionData; int dim = ((Integer)mDataFieldDims.get(resData.DataFieldIndex)).intValue(); DataResult res = resData.Result; double val = res.Value; Object[][] data = xDPTab2.getDrillDownData(addr); double sum = 0.0; if (data.length > 1) { for (int row = 1; row < data.length; ++row) { Object o = data[row][dim]; if (AnyConverter.isDouble(o)) sum += ((Double)o).doubleValue(); } } log.println(formatCell(addr) + ": " + data.length + " rows (" + (data.length-1) + " records)"); if (val != sum) testResult = false; } tRes.tested("getDrillDownData()", testResult); } public void _getPositionData() { boolean testResult = false; do { CellAddress addr = new CellAddress(); addr.Sheet = mRangeTable.Sheet; boolean rangeGood = true; for (int x = mRangeTable.StartColumn; x <= mRangeTable.EndColumn && rangeGood; ++x) { for (int y = mRangeTable.StartRow; y <= mRangeTable.EndRow && rangeGood; ++y) { addr.Column = x; addr.Row = y; log.println("checking " + formatCell(addr)); DataPilotTablePositionData posData = xDPTab2.getPositionData(addr); if (posData.PositionType == DataPilotTablePositionType.NOT_IN_TABLE) { log.println("specified cell address not in table: " + formatCell(addr)); rangeGood = false; continue; } switch (posData.PositionType) { case DataPilotTablePositionType.NOT_IN_TABLE: break; case DataPilotTablePositionType.COLUMN_HEADER: printHeaderData(posData); break; case DataPilotTablePositionType.ROW_HEADER: printHeaderData(posData); break; case DataPilotTablePositionType.RESULT: printResultData(posData); break; case DataPilotTablePositionType.OTHER: break; default: log.println("unknown position"); } } } if (!rangeGood) { log.println("table range check failed"); break; } testResult = true; } while (false); tRes.tested("getPositionData()", testResult); } public void _insertDrillDownSheet() { boolean testResult = true; int cellCount = mResultCells.size(); XSpreadsheets xSheets = xSheetDoc.getSheets(); XIndexAccess xIA = (XIndexAccess)UnoRuntime.queryInterface( XIndexAccess.class, xSheets); int sheetCount = xIA.getCount(); for (int i = 0; i < cellCount && testResult; ++i) { CellAddress addr = (CellAddress)mResultCells.get(i); Object[][] data = xDPTab2.getDrillDownData(addr); // sheet is always inserted at the current sheet position. xDPTab2.insertDrillDownSheet(addr); int newSheetCount = xIA.getCount(); if (newSheetCount == sheetCount + 1) { log.println("drill-down sheet for " + formatCell(addr) + " inserted"); if (data.length < 2) { // There is no data for this result. It should never have // inserted a drill-down sheet. log.println("new sheet inserted; however, there is no data for this result"); testResult = false; continue; } // Retrieve the object of the sheet just inserted. XSpreadsheet xSheet = null; try { xSheet = (XSpreadsheet)UnoRuntime.queryInterface( XSpreadsheet.class, xIA.getByIndex(addr.Sheet)); } catch (com.sun.star.uno.Exception e) { e.printStackTrace(); throw new StatusException("Failed to get the spreadsheet object.", e); } // Check the integrity of the data on the inserted sheet. if (!checkDrillDownSheetContent(xSheet, data)) { log.println("dataintegrity check on the inserted sheet failed"); testResult = false; continue; } log.println(" sheet data integrity check passed"); // Remove the sheet just inserted. XNamed xNamed = (XNamed)UnoRuntime.queryInterface(XNamed.class, xSheet); String name = xNamed.getName(); try { xSheets.removeByName(name); } catch (com.sun.star.uno.Exception e) { e.printStackTrace(); throw new StatusException("Failed to removed the inserted sheet named " + name + ".", e); } } else if (newSheetCount == sheetCount) { if (data.length > 1) { // There is data for this result. It should have inserted // a new sheet. log.println("no new sheet is inserted, despite the data being present."); testResult = false; } } else { log.println("what just happened!?"); testResult = false; } } tRes.tested("insertDrillDownSheet()", testResult); } public void _getOutputRangeByType() { boolean testResult = false; do { // Let's make sure this doesn't cause a crash. A range returned for an // out-of-bound condition is undefined. try { CellRangeAddress rangeOutOfBound = xDPTab2.getOutputRangeByType(-1); log.println("exception not raised"); break; } catch (IllegalArgumentException e) { log.println("exception raised on invalid range type (good)"); } try { CellRangeAddress rangeOutOfBound = xDPTab2.getOutputRangeByType(100); log.println("exception not raised"); break; } catch (IllegalArgumentException e) { log.println("exception raised on invalid range type (good)"); } // Check to make sure the whole range is not empty. if (mRangeWhole.EndColumn - mRangeWhole.StartColumn <= 0 || mRangeWhole.EndRow - mRangeWhole.EndColumn <= 0) { log.println("whole range is empty"); break; } log.println("whole range is not empty (good)"); // Table range must be of equal width with the whole range, and the same // bottom. if (mRangeTable.Sheet != mRangeWhole.Sheet || mRangeTable.StartColumn != mRangeWhole.StartColumn || mRangeTable.EndColumn != mRangeWhole.EndColumn || mRangeTable.EndRow != mRangeWhole.EndRow) { log.println("table range is incorrect"); break; } log.println("table range is correct"); // Result range must be smaller than the table range, and must share the // same lower-right corner. if (mRangeResult.Sheet != mRangeTable.Sheet || mRangeResult.StartColumn < mRangeTable.StartColumn || mRangeResult.StartRow < mRangeTable.StartRow || mRangeResult.EndColumn != mRangeTable.EndColumn || mRangeResult.EndRow != mRangeTable.EndRow) break; log.println("result range is correct"); testResult = true; } while (false); tRes.tested("getOutputRangeByType()", testResult); } private void printHeaderData(DataPilotTablePositionData posData) { DataPilotTableHeaderData header = (DataPilotTableHeaderData)posData.PositionData; String posType = ""; if (posData.PositionType == DataPilotTablePositionType.COLUMN_HEADER) posType = "column header"; else if (posData.PositionType == DataPilotTablePositionType.ROW_HEADER) posType = "row header"; log.println(posType + "; member name: " + header.MemberName + "; dimension: " + header.Dimension + "; hierarchy: " + header.Hierarchy + "; level: " + header.Level); } private void printResultData(DataPilotTablePositionData posData) { DataPilotTableResultData resultData = (DataPilotTableResultData)posData.PositionData; int dataId = resultData.DataFieldIndex; DataResult res = resultData.Result; double val = res.Value; int flags = res.Flags; int filterCount = resultData.FieldFilters.length; log.println("result; data field index: " + dataId + "; value: " + val + "; flags: " + flags + "; filter count: " + filterCount); for (int i = 0; i < filterCount; ++i) { DataPilotFieldFilter fil = resultData.FieldFilters[i]; log.println(" field name: " + fil.FieldName + "; match value: " + fil.MatchValue); } } private String formatCell(CellAddress addr) { String str = "(" + addr.Column + "," + addr.Row + ")"; return str; } private void printRange(String text, CellRangeAddress rangeAddr) { log.println(text + ": (" + rangeAddr.StartColumn + "," + rangeAddr.StartRow + ") - (" + rangeAddr.EndColumn + "," + rangeAddr.EndRow + ")"); } private void buildResultCells() throws ResultCellFailure { if (mResultCells != null) return; getOutputRanges(); mResultCells = new ArrayList(); for (int x = mRangeResult.StartColumn; x <= mRangeResult.EndColumn; ++x) { for (int y = mRangeResult.StartRow; y <= mRangeResult.EndRow; ++y) { CellAddress addr = new CellAddress(); addr.Sheet = mRangeResult.Sheet; addr.Column = x; addr.Row = y; DataPilotTablePositionData posData = xDPTab2.getPositionData(addr); if (posData.PositionType != DataPilotTablePositionType.RESULT) { log.println(formatCell(addr) + ": this is not a result cell"); throw new ResultCellFailure(); } mResultCells.add(addr); } } } private void buildDataFields() { mDataFieldDims = new ArrayList(); XDataPilotDescriptor xDesc = (XDataPilotDescriptor)UnoRuntime.queryInterface( XDataPilotDescriptor.class, xDPTab2); XIndexAccess xFields = xDesc.getDataPilotFields(); int fieldCount = xFields.getCount(); for (int i = 0; i < fieldCount; ++i) { try { Object field = xFields.getByIndex(i); XPropertySet propSet = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, field); DataPilotFieldOrientation orient = (DataPilotFieldOrientation)propSet.getPropertyValue("Orientation"); if (orient == DataPilotFieldOrientation.DATA) { Integer item = new Integer(i); mDataFieldDims.add(item); } } catch (com.sun.star.uno.Exception e) { e.printStackTrace(log); throw new StatusException( "Failed to get a field.", e); } } } private void getOutputRanges() { if (mRangeWhole != null && mRangeTable != null && mRangeResult != null) return; try { mRangeWhole = xDPTab2.getOutputRangeByType(DataPilotOutputRangeType.WHOLE); printRange("whole range ", mRangeWhole); mRangeTable = xDPTab2.getOutputRangeByType(DataPilotOutputRangeType.TABLE); printRange("table range ", mRangeTable); mRangeResult = xDPTab2.getOutputRangeByType(DataPilotOutputRangeType.RESULT); printRange("result range", mRangeResult); } catch (IllegalArgumentException e) { e.printStackTrace(log); throw new StatusException( "Failed to get output range by type.", e); } } private boolean checkDrillDownSheetContent(XSpreadsheet xSheet, Object[][] data) { CellAddress lastCell = getLastUsedCellAddress(xSheet, 0, 0); if (data.length <= 0 || lastCell.Row == 0 || lastCell.Column == 0) { log.println("empty data condition"); return false; } if (data.length != lastCell.Row + 1 || data[0].length != lastCell.Column + 1) { log.println("data size differs"); return false; } XCellRange xCR = null; try { xCR = xSheet.getCellRangeByPosition(0, 0, lastCell.Column, lastCell.Row); } catch (com.sun.star.lang.IndexOutOfBoundsException e) { return false; } XCellRangeData xCRD = (XCellRangeData)UnoRuntime.queryInterface( XCellRangeData.class, xCR); Object[][] sheetData = xCRD.getDataArray(); for (int x = 0; x < sheetData.length; ++x) { for (int y = 0; y < sheetData[x].length; ++y) { Object cell1 = sheetData[x][y]; Object cell2 = data[x][y]; if (AnyConverter.isString(cell1) && AnyConverter.isString(cell2)) { String s1 = (String)cell1, s2 = (String)(cell2); if (!s1.equals(s2)) { log.println("string cell values differ"); return false; } } else if (AnyConverter.isDouble(cell1) && AnyConverter.isDouble(cell2)) { double f1 = 0.0, f2 = 0.0; try { f1 = AnyConverter.toDouble(cell1); f2 = AnyConverter.toDouble(cell2); } catch (com.sun.star.lang.IllegalArgumentException e) { log.println("failed to convert cells to double"); return false; } if (f1 != f2) { log.println("numerical cell values differ"); return false; } } else { log.println("cell types differ"); return false; } } } return true; } private CellAddress getLastUsedCellAddress(XSpreadsheet xSheet, int nCol, int nRow) { try { XCellRange xRng = xSheet.getCellRangeByPosition(nCol, nRow, nCol, nRow); XSheetCellRange xSCR = (XSheetCellRange)UnoRuntime.queryInterface( XSheetCellRange.class, xRng); XSheetCellCursor xCursor = xSheet.createCursorByRange(xSCR); XCellCursor xCellCursor = (XCellCursor)UnoRuntime.queryInterface( XCellCursor.class, xCursor); xCellCursor.gotoEnd(); XCell xCell = xCursor.getCellByPosition(0, 0); XCellAddressable xCellAddr = (XCellAddressable)UnoRuntime.queryInterface( XCellAddressable.class, xCell); return xCellAddr.getCellAddress(); } catch (com.sun.star.lang.IndexOutOfBoundsException ex) { } return null; } }