001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2007-2011 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.olap4j; 011 012import mondrian.olap.Exp; 013import mondrian.olap.Util; 014import mondrian.rolap.RolapCell; 015import mondrian.rolap.SqlStatement; 016 017import org.apache.log4j.Logger; 018 019import org.olap4j.*; 020import org.olap4j.metadata.Property; 021 022import java.sql.ResultSet; 023import java.util.ArrayList; 024import java.util.Collections; 025import java.util.List; 026 027/** 028 * Implementation of {@link Cell} 029 * for the Mondrian OLAP engine. 030 * 031 * @author jhyde 032 * @since May 24, 2007 033 */ 034class MondrianOlap4jCell implements Cell { 035 private final int[] coordinates; 036 private final MondrianOlap4jCellSet olap4jCellSet; 037 final RolapCell cell; 038 039 /** 040 * Creates a MondrianOlap4jCell. 041 * 042 * @param coordinates Coordinates 043 * @param olap4jCellSet Cell set 044 * @param cell Cell in native Mondrian representation 045 */ 046 MondrianOlap4jCell( 047 int[] coordinates, 048 MondrianOlap4jCellSet olap4jCellSet, 049 RolapCell cell) 050 { 051 assert coordinates != null; 052 assert olap4jCellSet != null; 053 assert cell != null; 054 this.coordinates = coordinates; 055 this.olap4jCellSet = olap4jCellSet; 056 this.cell = cell; 057 } 058 059 public CellSet getCellSet() { 060 return olap4jCellSet; 061 } 062 063 public int getOrdinal() { 064 return (Integer) cell.getPropertyValue( 065 mondrian.olap.Property.CELL_ORDINAL.name); 066 } 067 068 public List<Integer> getCoordinateList() { 069 ArrayList<Integer> list = new ArrayList<Integer>(coordinates.length); 070 for (int coordinate : coordinates) { 071 list.add(coordinate); 072 } 073 return list; 074 } 075 076 public Object getPropertyValue(Property property) { 077 // We assume that mondrian properties have the same name as olap4j 078 // properties. 079 return cell.getPropertyValue(property.getName()); 080 } 081 082 public boolean isEmpty() { 083 // FIXME 084 return cell.isNull(); 085 } 086 087 public boolean isError() { 088 return cell.isError(); 089 } 090 091 public boolean isNull() { 092 return cell.isNull(); 093 } 094 095 public double getDoubleValue() throws OlapException { 096 Object o = cell.getValue(); 097 if (o instanceof Number) { 098 Number number = (Number) o; 099 return number.doubleValue(); 100 } 101 throw olap4jCellSet.olap4jStatement.olap4jConnection.helper 102 .createException(this, "not a number"); 103 } 104 105 public String getErrorText() { 106 Object o = cell.getValue(); 107 if (o instanceof Throwable) { 108 return ((Throwable) o).getMessage(); 109 } else { 110 return null; 111 } 112 } 113 114 public Object getValue() { 115 return cell.getValue(); 116 } 117 118 public String getFormattedValue() { 119 return cell.getFormattedValue(); 120 } 121 122 public ResultSet drillThrough() throws OlapException { 123 return drillThroughInternal( 124 -1, 125 -1, 126 new ArrayList<Exp>(), 127 false, 128 null, 129 null); 130 } 131 132 /** 133 * Executes drill-through on this cell. 134 * 135 * <p>Not a part of the public API. Package-protected because this method 136 * also implements the DRILLTHROUGH statement. 137 * 138 * @param maxRowCount Maximum number of rows to retrieve, <= 0 if unlimited 139 * @param firstRowOrdinal Ordinal of row to skip to (1-based), or 0 to 140 * start from beginning 141 * @param fields List of fields to return, expressed as MDX 142 * expressions. 143 * @param extendedContext If true, add non-constraining columns to the 144 * query for levels below each current member. 145 * This additional context makes the drill-through 146 * queries easier for humans to understand. 147 * @param logger Logger. If not null and debug is enabled, log SQL here 148 * @param rowCountSlot Slot into which the number of fact rows is written 149 * @return Result set 150 * @throws OlapException on error 151 */ 152 ResultSet drillThroughInternal( 153 int maxRowCount, 154 int firstRowOrdinal, 155 List<Exp> fields, 156 boolean extendedContext, 157 Logger logger, 158 int[] rowCountSlot) 159 throws OlapException 160 { 161 if (!cell.canDrillThrough()) { 162 return null; 163 } 164 if (rowCountSlot != null) { 165 rowCountSlot[0] = cell.getDrillThroughCount(); 166 } 167 final SqlStatement sqlStmt = 168 cell.drillThroughInternal( 169 maxRowCount, firstRowOrdinal, fields, extendedContext, 170 logger); 171 return sqlStmt.getWrappedResultSet(); 172 } 173 174 public void setValue( 175 Object newValue, 176 AllocationPolicy allocationPolicy, 177 Object... allocationArgs) 178 throws OlapException 179 { 180 Scenario scenario = 181 olap4jCellSet.olap4jStatement.olap4jConnection.getScenario(); 182 cell.setValue(scenario, newValue, allocationPolicy, allocationArgs); 183 } 184} 185 186// End MondrianOlap4jCell.java