Package org.pentaho.reporting.engine.classic.extensions.datasources.olap4j

Source Code of org.pentaho.reporting.engine.classic.extensions.datasources.olap4j.LegacyBandedMDXTableModel

/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2008 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors.  All rights reserved.
*/

package org.pentaho.reporting.engine.classic.extensions.datasources.olap4j;

import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;

import org.olap4j.Cell;
import org.olap4j.CellSet;
import org.olap4j.CellSetAxis;
import org.olap4j.Position;
import org.olap4j.metadata.Member;
import org.pentaho.reporting.engine.classic.core.MetaTableModel;
import org.pentaho.reporting.engine.classic.core.ReportDataFactoryException;
import org.pentaho.reporting.engine.classic.core.util.CloseableTableModel;
import org.pentaho.reporting.engine.classic.core.wizard.DataAttributes;
import org.pentaho.reporting.engine.classic.core.wizard.EmptyDataAttributes;
import org.pentaho.reporting.libraries.base.util.GenericObjectTable;

/**
* This tablemodel performs some preprocessing to get multi-dimensional resultset (with row and column headers) into a
* classical table-structure. The query must be a two-dimensional query or the whole process will break.
* <p/>
* This class exists for legacy reasons to provide existing reports the same view on MDX data as implemented in the
* Pentaho-Platform and the Report-Designer. It can also be somewhat useful if you have a requirement to produce banded
* reporting over a MDX data source.
*
* @author : Thomas Morgner
*/
public class LegacyBandedMDXTableModel extends AbstractTableModel
    implements CloseableTableModel, MetaTableModel
{
  private static final int AXIS_COLUMN = 0;
  private static final int AXIS_ROW = 1;

  private CellSet resultSet;
  private GenericObjectTable rowHeaders;
  private GenericObjectTable columnHeaders;
  private String[] columnNames;
  private int columnCount;
  private int rowCount;
  private boolean emptyAxisCase;
  private QueryResultWrapper resultWrapper;

  public LegacyBandedMDXTableModel(final QueryResultWrapper resultWrapper,
                                   final int queryLimitValue) throws ReportDataFactoryException
  {
    if (resultWrapper == null)
    {
      throw new NullPointerException("ResultSet returned was null");
    }
    this.resultWrapper = resultWrapper;
    this.resultSet = resultWrapper.getCellSet();

    final int axisCount = resultSet.getAxes().size();
    if (axisCount > 2)
    {
      throw new ReportDataFactoryException("Cannot handle results with more than two axes.");
    }
    this.rowHeaders = createRowHeaders();
    this.columnHeaders = createColumnHeaders();

    if (rowHeaders.getRowCount() > 0)
    {
      columnCount = rowHeaders.getColumnCount() + columnHeaders.getColumnCount();
    }
    else
    {
      columnCount = columnHeaders.getColumnCount();
    }
    if (columnCount == 0)
    {
      columnCount = 1;
      emptyAxisCase = true;
      columnNames = new String[]{"Measure"};
      rowCount = 1;
    }
    else
    {
      columnNames = new String[columnCount];
      for (int i = 0; i < columnNames.length; i++)
      {
        columnNames[i] = calcColumnName(i);
      }

      if (axisCount == 2)
      {
        rowCount = rowHeaders.getRowCount();
      }
      else
      {
        rowCount = Math.max(1, rowHeaders.getRowCount());
      }
    }

    if (queryLimitValue > 0)
    {
      rowCount = Math.min(queryLimitValue, rowCount);
    }
  }

  public String getColumnName(final int column)
  {
    return columnNames[column];
  }

  public Class<?> getColumnClass(final int columnIndex)
  {
    if (getRowCount() == 0)
    {
      return Object.class;
    }
    try
    {
      final Object targetClassObj = getValueAt(0, columnIndex);
      if (targetClassObj == null)
      {
        return Object.class;
      }
      else
      {
        return targetClassObj.getClass();
      }
    }
    catch (Exception e)
    {
      return Object.class;
    }
  }

  public int getRowCount()
  {
    return rowCount;
  }

  public int getColumnCount()
  {
    return columnCount;
  }

  public void close()
  {
    try
    {
      resultSet.close();
    }
    catch (SQLException e)
    {
      // ignore
    }
    try
    {
      final Statement statement = resultWrapper.getStatement();
      statement.close();
    }
    catch (SQLException e)
    {
      // ignore ..
    }
  }

  private String calcColumnName(int columnNumber)
  {
    if (columnNumber < rowHeaders.getColumnCount())
    {
      return calcColumnNameFromRowHeader(columnNumber);
    }
    else
    {
      columnNumber -= rowHeaders.getColumnCount();
    }

    final StringBuffer buf = new StringBuffer(32);
    for (int i = 0; i < columnHeaders.getRowCount(); i++)
    {
      if (i > 0 && buf.length() > 0)
      {
        buf.append('/');
      }
      final Object o = columnHeaders.getObject(i, columnNumber);
      if (o != null)
      {
        buf.append(String.valueOf(o));
      }
    }
    return buf.toString();
  }


  private String calcColumnNameFromRowHeader(final int columnNumber)
  {
    // Flatten out the column headers into one column-name
    final List<CellSetAxis> axes = this.resultSet.getAxes();
    final CellSetAxis axis = axes.get(AXIS_ROW);
    final List<Position> positions = axis.getPositions();
    final Position firstPosition = positions.get(0);
    final List<Member> memberList = firstPosition.getMembers();
    if (columnNumber < memberList.size())
    {
      final Member member = memberList.get(columnNumber);
      return member.getHierarchy().getName();
    }
    else
    {
      final Member member = memberList.get(memberList.size() - 1);
      return member.getHierarchy().getName() + '{' + columnNumber + '}';
    }
  }

  private GenericObjectTable createColumnHeaders()
  {
    final List<CellSetAxis> axes = this.resultSet.getAxes();
    if (axes.size() < 1)
    {
      return new GenericObjectTable();
    }
    final CellSetAxis axis = axes.get(AXIS_COLUMN);
    final List<Position> positions = axis.getPositions();
    final int colCount = positions.size();
    final GenericObjectTable result = new GenericObjectTable(20, Math.max(1, colCount));
    for (int c = 0; c < colCount; c++)
    {
      final Position position = positions.get(c);
      final List<Member> memberList = position.getMembers();
      Member member = null;
      final int rowCount = memberList.size();
      for (int r = 0; r < rowCount; r++)
      {
        member = memberList.get(r);
        if (member != null)
        {
          result.setObject(r, c, member.getName());
        }
      }

      if (member != null)
      {
        result.setObject(rowCount, c, member.getHierarchy().getName());
      }
    }
    return result;
  }

  /**
   * @return
   */
  private GenericObjectTable createRowHeaders()
  {
    final List<CellSetAxis> axes = this.resultSet.getAxes();
    if (axes.size() < 2)
    {
      return new GenericObjectTable();
    }
    final CellSetAxis axis = axes.get(AXIS_ROW);
    final List<Position> positions = axis.getPositions();
    final int rowCount = positions.size();
    final GenericObjectTable result = new GenericObjectTable(Math.max(1, rowCount), 5);

    for (int r = 0; r < rowCount; r++)
    {
      final Position position = positions.get(r);
      final List<Member> members = position.getMembers();
      Member member = null;
      final int colCount = members.size();
      for (int c = 0; c < colCount; c++)
      {
        member = members.get(c);
        result.setObject(r, c, member.getName());
      }
      if (member != null)
      {
        result.setObject(r, colCount, member.getHierarchy().getName());
      }
    }
    return result;
  }


  public Object getValueAt(final int rowIndex,
                           final int columnIndex)
  {
    if (resultSet == null)
    {
      return null;
    }

    if (columnIndex < rowHeaders.getColumnCount())
    {
      return rowHeaders.getObject(rowIndex, columnIndex);
    }

    if (emptyAxisCase)
    {
      final Cell cell = resultSet.getCell(0);
      if (cell.isNull())
      {
        return null;
      }
      return cell.getValue();
    }

    if (rowHeaders.getRowCount() == 0)
    {

      final List<Integer> key = new ArrayList<Integer>(1);
      key.add(columnIndex);
      final Cell cell = resultSet.getCell(key);
      if (cell.isNull())
      {
        return null;
      }
      return cell.getValue();
    }

    final List<Integer> key = new ArrayList<Integer>(2);
    key.add(Integer.valueOf(columnIndex - rowHeaders.getColumnCount()));
    key.add(Integer.valueOf(rowIndex));
    final Cell cell = resultSet.getCell(key);
    if (cell.isNull())
    {
      return null;
    }
    return cell.getValue();
  }

  public DataAttributes getCellDataAttributes(final int rowIndex,
                                              final int columnIndex)
  {
    // how does mondrian return formatting information?
    // I dont know yet ...
    if (resultSet == null)
    {
      return EmptyDataAttributes.INSTANCE;
    }

    if (columnIndex < rowHeaders.getColumnCount())
    {
      return EmptyDataAttributes.INSTANCE;
    }

    if (emptyAxisCase)
    {
      final Cell cell = resultSet.getCell(0);
      return new MDXMetaDataCellAttributes(EmptyDataAttributes.INSTANCE, cell);
    }

    if (rowHeaders.getRowCount() == 0)
    {

      final List<Integer> key = new ArrayList<Integer>(1);
      key.add(columnIndex);
      final Cell cell = resultSet.getCell(key);
      return new MDXMetaDataCellAttributes(EmptyDataAttributes.INSTANCE, cell);
    }


    final List<Integer> key = new ArrayList<Integer>(2);
    key.add(Integer.valueOf(columnIndex - rowHeaders.getColumnCount()));
    key.add(Integer.valueOf(rowIndex));
    final Cell c = resultSet.getCell(key);
    return new MDXMetaDataCellAttributes(EmptyDataAttributes.INSTANCE, c);
  }

  public boolean isCellDataAttributesSupported()
  {
    return true;
  }

  public DataAttributes getColumnAttributes(final int column)
  {
    return EmptyDataAttributes.INSTANCE;
  }

  public DataAttributes getTableAttributes()
  {
    return EmptyDataAttributes.INSTANCE;
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.extensions.datasources.olap4j.LegacyBandedMDXTableModel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.