001 /*
002 // $Id: //open/mondrian-release/3.0/src/main/mondrian/olap4j/MondrianOlap4jCell.java#2 $
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-release/3.0/src/main/mondrian/olap4j/MondrianOlap4jCell.java#2 $
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