001 /* 002 // $Id: //open/mondrian/src/main/mondrian/olap4j/MondrianOlap4jCell.java#1 $ 003 // This software is subject to the terms of the Common Public License 004 // Agreement, available at the following URL: 005 // http://www.opensource.org/licenses/cpl.html. 006 // Copyright (C) 2007-2007 Julian Hyde 007 // All Rights Reserved. 008 // You must accept the terms of that agreement to use this software. 009 */ 010 package mondrian.olap4j; 011 012 import org.olap4j.Cell; 013 import org.olap4j.CellSet; 014 import org.olap4j.OlapException; 015 import org.olap4j.metadata.Property; 016 017 import javax.sql.DataSource; 018 import java.util.List; 019 import java.util.ArrayList; 020 import java.sql.*; 021 import java.lang.reflect.Proxy; 022 023 import mondrian.util.DelegatingInvocationHandler; 024 025 /** 026 * Implementation of {@link Cell} 027 * for the Mondrian OLAP engine. 028 * 029 * @author jhyde 030 * @version $Id: //open/mondrian/src/main/mondrian/olap4j/MondrianOlap4jCell.java#1 $ 031 * @since May 24, 2007 032 */ 033 class MondrianOlap4jCell implements Cell { 034 private final int[] coordinates; 035 private final MondrianOlap4jCellSet olap4jCellSet; 036 private final mondrian.olap.Cell cell; 037 038 MondrianOlap4jCell( 039 int[] coordinates, 040 MondrianOlap4jCellSet olap4jCellSet, 041 mondrian.olap.Cell cell) 042 { 043 assert coordinates != null; 044 assert olap4jCellSet != null; 045 assert cell != null; 046 this.coordinates = coordinates; 047 this.olap4jCellSet = olap4jCellSet; 048 this.cell = cell; 049 } 050 051 public CellSet getCellSet() { 052 return olap4jCellSet; 053 } 054 055 public int getOrdinal() { 056 return (Integer) cell.getPropertyValue( 057 mondrian.olap.Property.CELL_ORDINAL.name); 058 } 059 060 public List<Integer> getCoordinateList() { 061 ArrayList<Integer> list = new ArrayList<Integer>(coordinates.length); 062 for (int coordinate : coordinates) { 063 list.add(coordinate); 064 } 065 return list; 066 } 067 068 public Object getPropertyValue(Property property) { 069 // We assume that mondrian properties have the same name as olap4j 070 // properties. 071 return cell.getPropertyValue(property.getName()); 072 } 073 074 public boolean isEmpty() { 075 // FIXME 076 return cell.isNull(); 077 } 078 079 public boolean isError() { 080 return cell.isError(); 081 } 082 083 public boolean isNull() { 084 return cell.isNull(); 085 } 086 087 public double getDoubleValue() throws OlapException { 088 Object o = cell.getValue(); 089 if (o instanceof Number) { 090 Number number = (Number) o; 091 return number.doubleValue(); 092 } 093 throw olap4jCellSet.olap4jStatement.olap4jConnection.helper 094 .createException(this, "not a number"); 095 } 096 097 public String getErrorText() { 098 Object o = cell.getValue(); 099 if (o instanceof Throwable) { 100 return ((Throwable) o).getMessage(); 101 } else { 102 return null; 103 } 104 } 105 106 public Object getValue() { 107 return cell.getValue(); 108 } 109 110 public String getFormattedValue() { 111 return cell.getFormattedValue(); 112 } 113 114 public ResultSet drillThrough() throws OlapException { 115 if (!cell.canDrillThrough()) { 116 return null; 117 } 118 final String sql = cell.getDrillThroughSQL(false); 119 final MondrianOlap4jConnection olap4jConnection = 120 this.olap4jCellSet.olap4jStatement.olap4jConnection; 121 final DataSource dataSource = 122 olap4jConnection.connection.getDataSource(); 123 try { 124 final Connection connection = dataSource.getConnection(); 125 final Statement statement = connection.createStatement(); 126 final ResultSet resultSet = statement.executeQuery(sql); 127 128 // To prevent a connection leak, wrap the result set in a proxy 129 // which automatically closes the connection (and hence also the 130 // statement and result set) when the result set is closed. 131 // The caller still has to remember to call ResultSet.close(), of 132 // course. 133 return (ResultSet) Proxy.newProxyInstance( 134 null, 135 new Class<?>[] {ResultSet.class}, 136 new MyDelegatingInvocationHandler(resultSet)); 137 } catch (SQLException e) { 138 throw olap4jConnection.helper.toOlapException(e); 139 } 140 } 141 142 // must be public for reflection to work 143 public static class MyDelegatingInvocationHandler 144 extends DelegatingInvocationHandler 145 { 146 private final ResultSet resultSet; 147 148 MyDelegatingInvocationHandler(ResultSet resultSet) { 149 this.resultSet = resultSet; 150 } 151 152 protected Object getTarget() { 153 return resultSet; 154 } 155 156 // implement ResultSet.close() 157 public void close() throws SQLException { 158 resultSet.getStatement().getConnection().close(); 159 } 160 } 161 } 162 163 // End MondrianOlap4jCell.java