1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
31 import java
.util
.ArrayList
;
33 import com
.sun
.star
.beans
.XPropertySet
;
34 import com
.sun
.star
.container
.XIndexAccess
;
35 import com
.sun
.star
.container
.XNamed
;
36 import com
.sun
.star
.lang
.IllegalArgumentException
;
37 import com
.sun
.star
.sheet
.*;
38 import com
.sun
.star
.table
.CellAddress
;
39 import com
.sun
.star
.table
.CellRangeAddress
;
40 import com
.sun
.star
.table
.XCell
;
41 import com
.sun
.star
.table
.XCellCursor
;
42 import com
.sun
.star
.table
.XCellRange
;
43 import com
.sun
.star
.uno
.AnyConverter
;
44 import com
.sun
.star
.uno
.UnoRuntime
;
46 import lib
.MultiMethodTest
;
48 import lib
.StatusException
;
51 * Testing <code>com.sun.star.sheet.XDataPilotTable2</code>
54 * <li><code> getDrillDownData()</code><li>
55 * <li><code> getPositionData()</code></li>
56 * <li><code> insertDrillDownSheet()</code></li>
57 * <li><code> getOutputRangeByType</code></li>
60 * @see com.sun.star.sheet.XDataPilotTable2
61 * @see com.sun.star.table.CellAddress
64 public class _XDataPilotTable2
extends MultiMethodTest
66 private XSpreadsheetDocument xSheetDoc
= null;
67 private XDataPilotTable2 xDPTab2
= null;
68 private CellRangeAddress mRangeWhole
= null;
69 private CellRangeAddress mRangeTable
= null;
70 private CellRangeAddress mRangeResult
= null;
71 private ArrayList mDataFieldDims
= null;
72 private ArrayList mResultCells
= null;
75 * exception to be thrown when obtaining a result data for a cell fails
76 * (probably because the cell is not a result cell).
78 private class ResultCellFailure
extends com
.sun
.star
.uno
.Exception
{}
80 protected void before()
82 Object o
= tEnv
.getObjRelation("DATAPILOTTABLE2");
83 xDPTab2
= (XDataPilotTable2
)UnoRuntime
.queryInterface(
84 XDataPilotTable2
.class, o
);
87 throw new StatusException(Status
.failed("Relation not found"));
89 xSheetDoc
= (XSpreadsheetDocument
)tEnv
.getObjRelation("SHEETDOCUMENT");
97 catch (ResultCellFailure e
)
99 e
.printStackTrace(log
);
100 throw new StatusException( "Failed to build result cells.", e
);
104 public void _getDrillDownData()
106 boolean testResult
= true;
107 int cellCount
= mResultCells
.size();
108 for (int i
= 0; i
< cellCount
; ++i
)
110 CellAddress addr
= (CellAddress
)mResultCells
.get(i
);
111 DataPilotTablePositionData posData
= xDPTab2
.getPositionData(addr
);
112 DataPilotTableResultData resData
= (DataPilotTableResultData
)posData
.PositionData
;
113 int dim
= ((Integer
)mDataFieldDims
.get(resData
.DataFieldIndex
)).intValue();
114 DataResult res
= resData
.Result
;
115 double val
= res
.Value
;
117 Object
[][] data
= xDPTab2
.getDrillDownData(addr
);
121 for (int row
= 1; row
< data
.length
; ++row
)
123 Object o
= data
[row
][dim
];
124 if (AnyConverter
.isDouble(o
))
125 sum
+= ((Double
)o
).doubleValue();
128 log
.println(formatCell(addr
) + ": " + data
.length
+ " rows (" + (data
.length
-1) + " records)");
133 tRes
.tested("getDrillDownData()", testResult
);
136 public void _getPositionData()
138 boolean testResult
= false;
142 CellAddress addr
= new CellAddress();
143 addr
.Sheet
= mRangeTable
.Sheet
;
145 boolean rangeGood
= true;
146 for (int x
= mRangeTable
.StartColumn
; x
<= mRangeTable
.EndColumn
&& rangeGood
; ++x
)
148 for (int y
= mRangeTable
.StartRow
; y
<= mRangeTable
.EndRow
&& rangeGood
; ++y
)
152 log
.println("checking " + formatCell(addr
));
153 DataPilotTablePositionData posData
= xDPTab2
.getPositionData(addr
);
154 if (posData
.PositionType
== DataPilotTablePositionType
.NOT_IN_TABLE
)
156 log
.println("specified cell address not in table: " + formatCell(addr
));
161 switch (posData
.PositionType
)
163 case DataPilotTablePositionType
.NOT_IN_TABLE
:
165 case DataPilotTablePositionType
.COLUMN_HEADER
:
166 printHeaderData(posData
);
168 case DataPilotTablePositionType
.ROW_HEADER
:
169 printHeaderData(posData
);
171 case DataPilotTablePositionType
.RESULT
:
172 printResultData(posData
);
174 case DataPilotTablePositionType
.OTHER
:
177 log
.println("unknown position");
184 log
.println("table range check failed");
192 tRes
.tested("getPositionData()", testResult
);
195 public void _insertDrillDownSheet()
197 boolean testResult
= true;
198 int cellCount
= mResultCells
.size();
199 XSpreadsheets xSheets
= xSheetDoc
.getSheets();
200 XIndexAccess xIA
= (XIndexAccess
)UnoRuntime
.queryInterface(
201 XIndexAccess
.class, xSheets
);
202 int sheetCount
= xIA
.getCount();
203 for (int i
= 0; i
< cellCount
&& testResult
; ++i
)
205 CellAddress addr
= (CellAddress
)mResultCells
.get(i
);
207 Object
[][] data
= xDPTab2
.getDrillDownData(addr
);
209 // sheet is always inserted at the current sheet position.
210 xDPTab2
.insertDrillDownSheet(addr
);
212 int newSheetCount
= xIA
.getCount();
213 if (newSheetCount
== sheetCount
+ 1)
215 log
.println("drill-down sheet for " + formatCell(addr
) + " inserted");
218 // There is no data for this result. It should never have
219 // inserted a drill-down sheet.
220 log
.println("new sheet inserted; however, there is no data for this result");
225 // Retrieve the object of the sheet just inserted.
226 XSpreadsheet xSheet
= null;
229 xSheet
= (XSpreadsheet
)UnoRuntime
.queryInterface(
230 XSpreadsheet
.class, xIA
.getByIndex(addr
.Sheet
));
232 catch (com
.sun
.star
.uno
.Exception e
)
235 throw new StatusException("Failed to get the spreadsheet object.", e
);
238 // Check the integrity of the data on the inserted sheet.
239 if (!checkDrillDownSheetContent(xSheet
, data
))
241 log
.println("dataintegrity check on the inserted sheet failed");
246 log
.println(" sheet data integrity check passed");
248 // Remove the sheet just inserted.
250 XNamed xNamed
= (XNamed
)UnoRuntime
.queryInterface(XNamed
.class, xSheet
);
251 String name
= xNamed
.getName();
254 xSheets
.removeByName(name
);
256 catch (com
.sun
.star
.uno
.Exception e
)
259 throw new StatusException("Failed to removed the inserted sheet named " + name
+ ".", e
);
262 else if (newSheetCount
== sheetCount
)
266 // There is data for this result. It should have inserted
268 log
.println("no new sheet is inserted, despite the data being present.");
274 log
.println("what just happened!?");
279 tRes
.tested("insertDrillDownSheet()", testResult
);
282 public void _getOutputRangeByType()
284 boolean testResult
= false;
288 // Let's make sure this doesn't cause a crash. A range returned for an
289 // out-of-bound condition is undefined.
292 CellRangeAddress rangeOutOfBound
= xDPTab2
.getOutputRangeByType(-1);
293 log
.println("exception not raised");
296 catch (IllegalArgumentException e
)
298 log
.println("exception raised on invalid range type (good)");
303 CellRangeAddress rangeOutOfBound
= xDPTab2
.getOutputRangeByType(100);
304 log
.println("exception not raised");
307 catch (IllegalArgumentException e
)
309 log
.println("exception raised on invalid range type (good)");
312 // Check to make sure the whole range is not empty.
313 if (mRangeWhole
.EndColumn
- mRangeWhole
.StartColumn
<= 0 ||
314 mRangeWhole
.EndRow
- mRangeWhole
.EndColumn
<= 0)
316 log
.println("whole range is empty");
320 log
.println("whole range is not empty (good)");
322 // Table range must be of equal width with the whole range, and the same
324 if (mRangeTable
.Sheet
!= mRangeWhole
.Sheet
||
325 mRangeTable
.StartColumn
!= mRangeWhole
.StartColumn
||
326 mRangeTable
.EndColumn
!= mRangeWhole
.EndColumn
||
327 mRangeTable
.EndRow
!= mRangeWhole
.EndRow
)
329 log
.println("table range is incorrect");
333 log
.println("table range is correct");
335 // Result range must be smaller than the table range, and must share the
336 // same lower-right corner.
337 if (mRangeResult
.Sheet
!= mRangeTable
.Sheet
||
338 mRangeResult
.StartColumn
< mRangeTable
.StartColumn
||
339 mRangeResult
.StartRow
< mRangeTable
.StartRow
||
340 mRangeResult
.EndColumn
!= mRangeTable
.EndColumn
||
341 mRangeResult
.EndRow
!= mRangeTable
.EndRow
)
344 log
.println("result range is correct");
350 tRes
.tested("getOutputRangeByType()", testResult
);
353 private void printHeaderData(DataPilotTablePositionData posData
)
355 DataPilotTableHeaderData header
= (DataPilotTableHeaderData
)posData
.PositionData
;
357 if (posData
.PositionType
== DataPilotTablePositionType
.COLUMN_HEADER
)
358 posType
= "column header";
359 else if (posData
.PositionType
== DataPilotTablePositionType
.ROW_HEADER
)
360 posType
= "row header";
362 log
.println(posType
+ "; member name: " + header
.MemberName
+ "; dimension: " +
363 header
.Dimension
+ "; hierarchy: " + header
.Hierarchy
+
364 "; level: " + header
.Level
);
367 private void printResultData(DataPilotTablePositionData posData
)
369 DataPilotTableResultData resultData
= (DataPilotTableResultData
)posData
.PositionData
;
370 int dataId
= resultData
.DataFieldIndex
;
371 DataResult res
= resultData
.Result
;
372 double val
= res
.Value
;
373 int flags
= res
.Flags
;
374 int filterCount
= resultData
.FieldFilters
.length
;
375 log
.println("result; data field index: " + dataId
+ "; value: " + val
+ "; flags: " + flags
+
376 "; filter count: " + filterCount
);
378 for (int i
= 0; i
< filterCount
; ++i
)
380 DataPilotFieldFilter fil
= resultData
.FieldFilters
[i
];
381 log
.println(" field name: " + fil
.FieldName
+ "; match value: " + fil
.MatchValue
);
385 private String
formatCell(CellAddress addr
)
387 String str
= "(" + addr
.Column
+ "," + addr
.Row
+ ")";
391 private void printRange(String text
, CellRangeAddress rangeAddr
)
393 log
.println(text
+ ": (" + rangeAddr
.StartColumn
+ "," + rangeAddr
.StartRow
+ ") - (" +
394 rangeAddr
.EndColumn
+ "," + rangeAddr
.EndRow
+ ")");
397 private void buildResultCells() throws ResultCellFailure
399 if (mResultCells
!= null)
404 mResultCells
= new ArrayList();
405 for (int x
= mRangeResult
.StartColumn
; x
<= mRangeResult
.EndColumn
; ++x
)
407 for (int y
= mRangeResult
.StartRow
; y
<= mRangeResult
.EndRow
; ++y
)
409 CellAddress addr
= new CellAddress();
410 addr
.Sheet
= mRangeResult
.Sheet
;
413 DataPilotTablePositionData posData
= xDPTab2
.getPositionData(addr
);
414 if (posData
.PositionType
!= DataPilotTablePositionType
.RESULT
)
416 log
.println(formatCell(addr
) + ": this is not a result cell");
417 throw new ResultCellFailure();
419 mResultCells
.add(addr
);
424 private void buildDataFields()
426 mDataFieldDims
= new ArrayList();
427 XDataPilotDescriptor xDesc
= (XDataPilotDescriptor
)UnoRuntime
.queryInterface(
428 XDataPilotDescriptor
.class, xDPTab2
);
430 XIndexAccess xFields
= xDesc
.getDataPilotFields();
431 int fieldCount
= xFields
.getCount();
432 for (int i
= 0; i
< fieldCount
; ++i
)
436 Object field
= xFields
.getByIndex(i
);
437 XPropertySet propSet
= (XPropertySet
)UnoRuntime
.queryInterface(
438 XPropertySet
.class, field
);
439 DataPilotFieldOrientation orient
=
440 (DataPilotFieldOrientation
)propSet
.getPropertyValue("Orientation");
441 if (orient
== DataPilotFieldOrientation
.DATA
)
443 Integer item
= new Integer(i
);
444 mDataFieldDims
.add(item
);
447 catch (com
.sun
.star
.uno
.Exception e
)
449 e
.printStackTrace(log
);
450 throw new StatusException( "Failed to get a field.", e
);
455 private void getOutputRanges()
457 if (mRangeWhole
!= null && mRangeTable
!= null && mRangeResult
!= null)
462 mRangeWhole
= xDPTab2
.getOutputRangeByType(DataPilotOutputRangeType
.WHOLE
);
463 printRange("whole range ", mRangeWhole
);
464 mRangeTable
= xDPTab2
.getOutputRangeByType(DataPilotOutputRangeType
.TABLE
);
465 printRange("table range ", mRangeTable
);
466 mRangeResult
= xDPTab2
.getOutputRangeByType(DataPilotOutputRangeType
.RESULT
);
467 printRange("result range", mRangeResult
);
469 catch (IllegalArgumentException e
)
471 e
.printStackTrace(log
);
472 throw new StatusException( "Failed to get output range by type.", e
);
476 private boolean checkDrillDownSheetContent(XSpreadsheet xSheet
, Object
[][] data
)
478 CellAddress lastCell
= getLastUsedCellAddress(xSheet
, 0, 0);
479 if (data
.length
<= 0 || lastCell
.Row
== 0 || lastCell
.Column
== 0)
481 log
.println("empty data condition");
485 if (data
.length
!= lastCell
.Row
+ 1 || data
[0].length
!= lastCell
.Column
+ 1)
487 log
.println("data size differs");
491 XCellRange xCR
= null;
494 xCR
= xSheet
.getCellRangeByPosition(0, 0, lastCell
.Column
, lastCell
.Row
);
496 catch (com
.sun
.star
.lang
.IndexOutOfBoundsException e
)
501 XCellRangeData xCRD
= (XCellRangeData
)UnoRuntime
.queryInterface(
502 XCellRangeData
.class, xCR
);
504 Object
[][] sheetData
= xCRD
.getDataArray();
505 for (int x
= 0; x
< sheetData
.length
; ++x
)
507 for (int y
= 0; y
< sheetData
[x
].length
; ++y
)
509 Object cell1
= sheetData
[x
][y
];
510 Object cell2
= data
[x
][y
];
511 if (AnyConverter
.isString(cell1
) && AnyConverter
.isString(cell2
))
513 String s1
= (String
)cell1
, s2
= (String
)(cell2
);
516 log
.println("string cell values differ");
520 else if (AnyConverter
.isDouble(cell1
) && AnyConverter
.isDouble(cell2
))
522 double f1
= 0.0, f2
= 0.0;
525 f1
= AnyConverter
.toDouble(cell1
);
526 f2
= AnyConverter
.toDouble(cell2
);
528 catch (com
.sun
.star
.lang
.IllegalArgumentException e
)
530 log
.println("failed to convert cells to double");
536 log
.println("numerical cell values differ");
542 log
.println("cell types differ");
551 private CellAddress
getLastUsedCellAddress(XSpreadsheet xSheet
, int nCol
, int nRow
)
555 XCellRange xRng
= xSheet
.getCellRangeByPosition(nCol
, nRow
, nCol
, nRow
);
556 XSheetCellRange xSCR
= (XSheetCellRange
)UnoRuntime
.queryInterface(
557 XSheetCellRange
.class, xRng
);
559 XSheetCellCursor xCursor
= xSheet
.createCursorByRange(xSCR
);
560 XCellCursor xCellCursor
= (XCellCursor
)UnoRuntime
.queryInterface(
561 XCellCursor
.class, xCursor
);
563 xCellCursor
.gotoEnd();
564 XCell xCell
= xCursor
.getCellByPosition(0, 0);
565 XCellAddressable xCellAddr
= (XCellAddressable
)UnoRuntime
.queryInterface(
566 XCellAddressable
.class, xCell
);
568 return xCellAddr
.getCellAddress();
570 catch (com
.sun
.star
.lang
.IndexOutOfBoundsException ex
)