blob: 492fea2aea4aba1d5a8bfc9a46e9e0cf9ae158be [file] [log] [blame]
/**************************************************************
*
* 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 <code>com.sun.star.sheet.XDataPilotTable2</code>
* interface methods :
* <ul>
* <li><code> getDrillDownData()</code><li>
* <li><code> getPositionData()</code></li>
* <li><code> insertDrillDownSheet()</code></li>
* <li><code> getOutputRangeByType</code></li>
* </ul>
*
* @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;
}
}