2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 import java
.util
.ArrayList
;
24 import com
.sun
.star
.beans
.XPropertySet
;
25 import com
.sun
.star
.container
.XIndexAccess
;
26 import com
.sun
.star
.container
.XNamed
;
27 import com
.sun
.star
.lang
.IllegalArgumentException
;
28 import com
.sun
.star
.sheet
.*;
29 import com
.sun
.star
.table
.CellAddress
;
30 import com
.sun
.star
.table
.CellRangeAddress
;
31 import com
.sun
.star
.table
.XCell
;
32 import com
.sun
.star
.table
.XCellCursor
;
33 import com
.sun
.star
.table
.XCellRange
;
34 import com
.sun
.star
.uno
.AnyConverter
;
35 import com
.sun
.star
.uno
.UnoRuntime
;
37 import lib
.MultiMethodTest
;
39 import lib
.StatusException
;
42 * Testing <code>com.sun.star.sheet.XDataPilotTable2</code>
45 * <li><code> getDrillDownData()</code><li>
46 * <li><code> getPositionData()</code></li>
47 * <li><code> insertDrillDownSheet()</code></li>
48 * <li><code> getOutputRangeByType</code></li>
51 * @see com.sun.star.sheet.XDataPilotTable2
52 * @see com.sun.star.table.CellAddress
55 public class _XDataPilotTable2
extends MultiMethodTest
57 private XSpreadsheetDocument xSheetDoc
= null;
58 private XDataPilotTable2 xDPTab2
= null;
59 private CellRangeAddress mRangeWhole
= null;
60 private CellRangeAddress mRangeTable
= null;
61 private CellRangeAddress mRangeResult
= null;
62 private ArrayList
<Integer
> mDataFieldDims
= null;
63 private ArrayList
<CellAddress
> mResultCells
= null;
65 public XDataPilotTable2 oObj
;
68 * exception to be thrown when obtaining a result data for a cell fails
69 * (probably because the cell is not a result cell).
71 private class ResultCellFailure
extends com
.sun
.star
.uno
.Exception
{}
74 protected void before()
76 Object o
= tEnv
.getObjRelation("DATAPILOTTABLE2");
77 xDPTab2
= UnoRuntime
.queryInterface(
78 XDataPilotTable2
.class, o
);
81 throw new StatusException(Status
.failed("Relation not found"));
83 xSheetDoc
= (XSpreadsheetDocument
)tEnv
.getObjRelation("SHEETDOCUMENT");
91 catch (ResultCellFailure e
)
93 e
.printStackTrace(log
);
94 throw new StatusException( "Failed to build result cells.", e
);
98 public void _getDrillDownData()
100 boolean testResult
= true;
101 int cellCount
= mResultCells
.size();
102 for (int i
= 0; i
< cellCount
; ++i
)
104 CellAddress addr
= mResultCells
.get(i
);
105 DataPilotTablePositionData posData
= xDPTab2
.getPositionData(addr
);
106 DataPilotTableResultData resData
= (DataPilotTableResultData
)posData
.PositionData
;
107 int dim
= mDataFieldDims
.get(resData
.DataFieldIndex
).intValue();
108 DataResult res
= resData
.Result
;
109 double val
= res
.Value
;
111 Object
[][] data
= xDPTab2
.getDrillDownData(addr
);
115 for (int row
= 1; row
< data
.length
; ++row
)
117 Object o
= data
[row
][dim
];
118 if (AnyConverter
.isDouble(o
))
119 sum
+= ((Double
)o
).doubleValue();
122 log
.println(formatCell(addr
) + ": " + data
.length
+ " rows (" + (data
.length
-1) + " records)");
127 tRes
.tested("getDrillDownData()", testResult
);
130 public void _getPositionData()
132 boolean testResult
= false;
136 CellAddress addr
= new CellAddress();
137 addr
.Sheet
= mRangeTable
.Sheet
;
139 boolean rangeGood
= true;
140 for (int x
= mRangeTable
.StartColumn
; x
<= mRangeTable
.EndColumn
&& rangeGood
; ++x
)
142 for (int y
= mRangeTable
.StartRow
; y
<= mRangeTable
.EndRow
&& rangeGood
; ++y
)
146 log
.println("checking " + formatCell(addr
));
147 DataPilotTablePositionData posData
= xDPTab2
.getPositionData(addr
);
148 if (posData
.PositionType
== DataPilotTablePositionType
.NOT_IN_TABLE
)
150 log
.println("specified cell address not in table: " + formatCell(addr
));
155 switch (posData
.PositionType
)
157 case DataPilotTablePositionType
.NOT_IN_TABLE
:
159 case DataPilotTablePositionType
.COLUMN_HEADER
:
160 printHeaderData(posData
);
162 case DataPilotTablePositionType
.ROW_HEADER
:
163 printHeaderData(posData
);
165 case DataPilotTablePositionType
.RESULT
:
166 printResultData(posData
);
168 case DataPilotTablePositionType
.OTHER
:
171 log
.println("unknown position");
178 log
.println("table range check failed");
186 tRes
.tested("getPositionData()", testResult
);
189 public void _insertDrillDownSheet()
191 boolean testResult
= true;
192 int cellCount
= mResultCells
.size();
193 XSpreadsheets xSheets
= xSheetDoc
.getSheets();
194 XIndexAccess xIA
= UnoRuntime
.queryInterface(
195 XIndexAccess
.class, xSheets
);
196 int sheetCount
= xIA
.getCount();
197 for (int i
= 0; i
< cellCount
&& testResult
; ++i
)
199 CellAddress addr
= mResultCells
.get(i
);
201 Object
[][] data
= xDPTab2
.getDrillDownData(addr
);
203 // sheet is always inserted at the current sheet position.
204 xDPTab2
.insertDrillDownSheet(addr
);
206 int newSheetCount
= xIA
.getCount();
207 if (newSheetCount
== sheetCount
+ 1)
209 log
.println("drill-down sheet for " + formatCell(addr
) + " inserted");
212 // There is no data for this result. It should never have
213 // inserted a drill-down sheet.
214 log
.println("new sheet inserted; however, there is no data for this result");
219 // Retrieve the object of the sheet just inserted.
220 XSpreadsheet xSheet
= null;
223 xSheet
= UnoRuntime
.queryInterface(
224 XSpreadsheet
.class, xIA
.getByIndex(addr
.Sheet
));
226 catch (com
.sun
.star
.uno
.Exception e
)
229 throw new StatusException("Failed to get the spreadsheet object.", e
);
232 // Check the integrity of the data on the inserted sheet.
233 if (!checkDrillDownSheetContent(xSheet
, data
))
235 log
.println("dataintegrity check on the inserted sheet failed");
240 log
.println(" sheet data integrity check passed");
242 // Remove the sheet just inserted.
244 XNamed xNamed
= UnoRuntime
.queryInterface(XNamed
.class, xSheet
);
245 String name
= xNamed
.getName();
248 xSheets
.removeByName(name
);
250 catch (com
.sun
.star
.uno
.Exception e
)
253 throw new StatusException("Failed to removed the inserted sheet named " + name
+ ".", e
);
256 else if (newSheetCount
== sheetCount
)
260 // There is data for this result. It should have inserted
262 log
.println("no new sheet is inserted, despite the data being present.");
268 log
.println("what just happened!?");
273 tRes
.tested("insertDrillDownSheet()", testResult
);
276 public void _getOutputRangeByType()
278 boolean testResult
= false;
282 // Let's make sure this doesn't cause a crash. A range returned for an
283 // out-of-bound condition is undefined.
286 xDPTab2
.getOutputRangeByType(-1);
287 log
.println("exception not raised");
290 catch (IllegalArgumentException e
)
292 log
.println("exception raised on invalid range type (good)");
297 xDPTab2
.getOutputRangeByType(100);
298 log
.println("exception not raised");
301 catch (IllegalArgumentException e
)
303 log
.println("exception raised on invalid range type (good)");
306 // Check to make sure the whole range is not empty.
307 if (mRangeWhole
.EndColumn
- mRangeWhole
.StartColumn
<= 0 ||
308 mRangeWhole
.EndRow
- mRangeWhole
.EndColumn
<= 0)
310 log
.println("whole range is empty");
314 log
.println("whole range is not empty (good)");
316 // Table range must be of equal width with the whole range, and the same
318 if (mRangeTable
.Sheet
!= mRangeWhole
.Sheet
||
319 mRangeTable
.StartColumn
!= mRangeWhole
.StartColumn
||
320 mRangeTable
.EndColumn
!= mRangeWhole
.EndColumn
||
321 mRangeTable
.EndRow
!= mRangeWhole
.EndRow
)
323 log
.println("table range is incorrect");
327 log
.println("table range is correct");
329 // Result range must be smaller than the table range, and must share the
330 // same lower-right corner.
331 if (mRangeResult
.Sheet
!= mRangeTable
.Sheet
||
332 mRangeResult
.StartColumn
< mRangeTable
.StartColumn
||
333 mRangeResult
.StartRow
< mRangeTable
.StartRow
||
334 mRangeResult
.EndColumn
!= mRangeTable
.EndColumn
||
335 mRangeResult
.EndRow
!= mRangeTable
.EndRow
)
338 log
.println("result range is correct");
344 tRes
.tested("getOutputRangeByType()", testResult
);
347 private void printHeaderData(DataPilotTablePositionData posData
)
349 DataPilotTableHeaderData header
= (DataPilotTableHeaderData
)posData
.PositionData
;
351 if (posData
.PositionType
== DataPilotTablePositionType
.COLUMN_HEADER
)
352 posType
= "column header";
353 else if (posData
.PositionType
== DataPilotTablePositionType
.ROW_HEADER
)
354 posType
= "row header";
356 log
.println(posType
+ "; member name: " + header
.MemberName
+ "; dimension: " +
357 header
.Dimension
+ "; hierarchy: " + header
.Hierarchy
+
358 "; level: " + header
.Level
);
361 private void printResultData(DataPilotTablePositionData posData
)
363 DataPilotTableResultData resultData
= (DataPilotTableResultData
)posData
.PositionData
;
364 int dataId
= resultData
.DataFieldIndex
;
365 DataResult res
= resultData
.Result
;
366 double val
= res
.Value
;
367 int flags
= res
.Flags
;
368 int filterCount
= resultData
.FieldFilters
.length
;
369 log
.println("result; data field index: " + dataId
+ "; value: " + val
+ "; flags: " + flags
+
370 "; filter count: " + filterCount
);
372 for (int i
= 0; i
< filterCount
; ++i
)
374 DataPilotFieldFilter fil
= resultData
.FieldFilters
[i
];
375 log
.println(" field name: " + fil
.FieldName
+ "; match value: " + fil
.MatchValue
);
379 private String
formatCell(CellAddress addr
)
381 String str
= "(" + addr
.Column
+ "," + addr
.Row
+ ")";
385 private void printRange(String text
, CellRangeAddress rangeAddr
)
387 log
.println(text
+ ": (" + rangeAddr
.StartColumn
+ "," + rangeAddr
.StartRow
+ ") - (" +
388 rangeAddr
.EndColumn
+ "," + rangeAddr
.EndRow
+ ")");
391 private void buildResultCells() throws ResultCellFailure
393 if (mResultCells
!= null)
398 mResultCells
= new ArrayList
<CellAddress
>();
399 for (int x
= mRangeResult
.StartColumn
; x
<= mRangeResult
.EndColumn
; ++x
)
401 for (int y
= mRangeResult
.StartRow
; y
<= mRangeResult
.EndRow
; ++y
)
403 CellAddress addr
= new CellAddress();
404 addr
.Sheet
= mRangeResult
.Sheet
;
407 DataPilotTablePositionData posData
= xDPTab2
.getPositionData(addr
);
408 if (posData
.PositionType
!= DataPilotTablePositionType
.RESULT
)
410 log
.println(formatCell(addr
) + ": this is not a result cell");
411 throw new ResultCellFailure();
413 mResultCells
.add(addr
);
418 private void buildDataFields()
420 mDataFieldDims
= new ArrayList
<Integer
>();
421 XDataPilotDescriptor xDesc
= UnoRuntime
.queryInterface(
422 XDataPilotDescriptor
.class, xDPTab2
);
424 XIndexAccess xFields
= xDesc
.getDataPilotFields();
425 int fieldCount
= xFields
.getCount();
426 for (int i
= 0; i
< fieldCount
; ++i
)
430 Object field
= xFields
.getByIndex(i
);
431 XPropertySet propSet
= UnoRuntime
.queryInterface(
432 XPropertySet
.class, field
);
433 DataPilotFieldOrientation orient
=
434 (DataPilotFieldOrientation
)propSet
.getPropertyValue("Orientation");
435 if (orient
== DataPilotFieldOrientation
.DATA
)
437 Integer item
= Integer
.valueOf(i
);
438 mDataFieldDims
.add(item
);
441 catch (com
.sun
.star
.uno
.Exception e
)
443 e
.printStackTrace(log
);
444 throw new StatusException( "Failed to get a field.", e
);
449 private void getOutputRanges()
451 if (mRangeWhole
!= null && mRangeTable
!= null && mRangeResult
!= null)
456 mRangeWhole
= xDPTab2
.getOutputRangeByType(DataPilotOutputRangeType
.WHOLE
);
457 printRange("whole range ", mRangeWhole
);
458 mRangeTable
= xDPTab2
.getOutputRangeByType(DataPilotOutputRangeType
.TABLE
);
459 printRange("table range ", mRangeTable
);
460 mRangeResult
= xDPTab2
.getOutputRangeByType(DataPilotOutputRangeType
.RESULT
);
461 printRange("result range", mRangeResult
);
463 catch (IllegalArgumentException e
)
465 e
.printStackTrace(log
);
466 throw new StatusException( "Failed to get output range by type.", e
);
470 private boolean checkDrillDownSheetContent(XSpreadsheet xSheet
, Object
[][] data
)
472 CellAddress lastCell
= getLastUsedCellAddress(xSheet
, 0, 0);
473 if (data
.length
<= 0 || lastCell
.Row
== 0 || lastCell
.Column
== 0)
475 log
.println("empty data condition");
479 if (data
.length
!= lastCell
.Row
+ 1 || data
[0].length
!= lastCell
.Column
+ 1)
481 log
.println("data size differs");
485 XCellRange xCR
= null;
488 xCR
= xSheet
.getCellRangeByPosition(0, 0, lastCell
.Column
, lastCell
.Row
);
490 catch (com
.sun
.star
.lang
.IndexOutOfBoundsException e
)
495 XCellRangeData xCRD
= UnoRuntime
.queryInterface(
496 XCellRangeData
.class, xCR
);
498 Object
[][] sheetData
= xCRD
.getDataArray();
499 for (int x
= 0; x
< sheetData
.length
; ++x
)
501 for (int y
= 0; y
< sheetData
[x
].length
; ++y
)
503 Object cell1
= sheetData
[x
][y
];
504 Object cell2
= data
[x
][y
];
505 if (AnyConverter
.isString(cell1
) && AnyConverter
.isString(cell2
))
507 String s1
= (String
)cell1
, s2
= (String
)(cell2
);
510 log
.println("string cell values differ");
514 else if (AnyConverter
.isDouble(cell1
) && AnyConverter
.isDouble(cell2
))
516 double f1
= 0.0, f2
= 0.0;
519 f1
= AnyConverter
.toDouble(cell1
);
520 f2
= AnyConverter
.toDouble(cell2
);
522 catch (com
.sun
.star
.lang
.IllegalArgumentException e
)
524 log
.println("failed to convert cells to double");
530 log
.println("numerical cell values differ");
536 log
.println("cell types differ");
545 private CellAddress
getLastUsedCellAddress(XSpreadsheet xSheet
, int nCol
, int nRow
)
549 XCellRange xRng
= xSheet
.getCellRangeByPosition(nCol
, nRow
, nCol
, nRow
);
550 XSheetCellRange xSCR
= UnoRuntime
.queryInterface(
551 XSheetCellRange
.class, xRng
);
553 XSheetCellCursor xCursor
= xSheet
.createCursorByRange(xSCR
);
554 XCellCursor xCellCursor
= UnoRuntime
.queryInterface(
555 XCellCursor
.class, xCursor
);
557 xCellCursor
.gotoEnd();
558 XCell xCell
= xCursor
.getCellByPosition(0, 0);
559 XCellAddressable xCellAddr
= UnoRuntime
.queryInterface(
560 XCellAddressable
.class, xCell
);
562 return xCellAddr
.getCellAddress();
564 catch (com
.sun
.star
.lang
.IndexOutOfBoundsException ex
)