Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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) 2010 Webdetails Consulting, .  All rights reserved.
  */
 package pt.webdetails.cda.utils.mondrian;
 
 import java.util.List;
 
 
 import  mondrian.olap.Axis;
 import  mondrian.olap.Cell;
 import  mondrian.olap.Dimension;
 import  mondrian.olap.Member;
 import  mondrian.olap.Position;
 import  mondrian.olap.Result;
 
 import  org.apache.commons.logging.Log;
 import  org.apache.commons.logging.LogFactory;
 import  org.pentaho.reporting.engine.classic.core.MetaAttributeNames;
 import  org.pentaho.reporting.engine.classic.core.MetaTableModel;
 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.DefaultConceptQueryMapper;
 import  org.pentaho.reporting.engine.classic.core.wizard.DefaultDataAttributes;
 import  org.pentaho.reporting.engine.classic.core.wizard.EmptyDataAttributes;
 import  org.pentaho.reporting.engine.classic.extensions.datasources.mondrian.DenormalizedMDXTableModel;
 import  org.pentaho.reporting.engine.classic.extensions.datasources.mondrian.MDXMetaDataCellAttributes;
 import  org.pentaho.reporting.engine.classic.extensions.datasources.mondrian.MDXMetaDataMemberAttributes;
 import  org.pentaho.reporting.engine.classic.extensions.datasources.mondrian.MondrianUtil;
 import  org.pentaho.reporting.libraries.base.util.FastStack;

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.

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(s):
: Thomas Morgner
 
 {
   "UnnecessaryUnboxing"
 })
         implements CloseableTableModel, MetaTableModel
 {
 
   private static final Log logger = LogFactory.getLog(CompactBandedMDXTableModel.class);
   private boolean noMeasures;
   private Result resultSet;
   private int rowCount;
   private int columnCount;
   private String[] columnNames;
   private int[] axesSize;
   private int[] columnToAxisPosition;
   private Dimension[] columnToDimensionMapping;
 
   public CompactBandedMDXTableModel(final Result resultSetfinal int rowLimit)
   {
     if (resultSet == null)
     {
       throw new NullPointerException("ResultSet returned was null");
     }
     this. = resultSet;
 
     // rowcount is the product of all axis-sizes. If an axis contains more than one member, then
     // Mondrian already performs the crossjoin for us.
 
     // column count is the count of all hierachies of all axis.
 
     final Axis[] axes = this..getAxes();
     this. = 0;
     this. = new int[axes.length];
     final int[] axesMembers = new int[axes.length];
     final List<Dimension>[] dimensionsForMembersPerAxis = new List[axes.length];
     final List<Integer>[] membersPerAxis = new List[axes.length];
 
     // process the column axis first ..
     if (. > 0)
     {
       final Axis axis = axes[0];
       final List<Position> positions = axis.getPositions();
      [0] = positions.size();
      if (positions.isEmpty())
      {
         = true;
      }
    }
    // Axis contains (zero or more) positions, which contains (zero or more) members
    for (int axesIndex = axes.length - 1; axesIndex >= 1; axesIndex -= 1)
    {
      final Axis axis = axes[axesIndex];
      final List<Position> positions = axis.getPositions();
      [axesIndex] = positions.size();
      if (positions.isEmpty())
      {
         = true;
      }
      final ArrayList<IntegermemberList = new ArrayList<Integer>();
      final ArrayList<Dimension> dimensionsForMembers = new ArrayList<Dimension>();
      for (int positionsIndex = 0; positionsIndex < positions.size(); positionsIndex++)
      {
        final Position position = positions.get(positionsIndex);
        for (int positionIndex = 0; positionIndex < position.size(); positionIndex++)
        {
          Member m = position.get(positionIndex);
          final Dimension dimension = m.getDimension();
          int hierarchyLevelCount = 1; // Originally was 0
          // Change compared to BandedMDXTM - we don't want all levels
          while (false && m != null)
          {
            m = m.getParentMember();
            hierarchyLevelCount += 1;
          }
          if (memberList.size() <= positionIndex)
          {
            memberList.add(hierarchyLevelCount);
            dimensionsForMembers.add(dimension);
          }
          else
          {
            final Integer existingLevel = memberList.get(positionIndex);
            if (existingLevel.intValue() < hierarchyLevelCount)
            {
              memberList.set(positionIndexhierarchyLevelCount);
              dimensionsForMembers.set(positionIndexdimension);
            }
          }
        }
      }
      int memberCount = 0;
      for (int i = 0; i < memberList.size(); i++)
      {
        memberCount += memberList.get(i);
      }
      axesMembers[axesIndex] = memberCount;
      dimensionsForMembersPerAxis[axesIndex] = dimensionsForMembers;
      membersPerAxis[axesIndex] = memberList;
    }
    if (. > 1)
    {
       = [1];
      for (int i = 2; i < .i++)
      {
        final int size = [i];
         *= size;
      }
    }
    if ( == false)
    {
       = Math.max(1, );
    }
    if (. == 0)
    {
       = 1;
    }
    else if (. > 0)
    {
       = [0];
    }
    for (int i = 1; i < axesMembers.lengthi++)
    {
       += axesMembers[i];
    }
     = new String[];
     = new Dimension[];
     = new int[];
    int columnIndex = 0;
    int dimColIndex = 0;
    final FastStack memberStack = new FastStack();
    for (int axesIndex = axes.length - 1; axesIndex >= 1; axesIndex -= 1)
    {
      final Axis axis = axes[axesIndex];
      final List<Position> positions = axis.getPositions();
      final LinkedHashSet<StringcolumnNamesSet = new LinkedHashSet<String>();
      for (int positionsIndex = 0; positionsIndex < positions.size(); positionsIndex++)
      {
        final Position position = positions.get(positionsIndex);
        for (int positionIndex = 0; positionIndex < position.size(); positionIndex++)
        {
          memberStack.clear();
          Member m = position.get(positionIndex);
          // Get member's hierarchy
          final String name = m.getHierarchy().getName();
          if (columnNamesSet.contains(name) == false)
          {
            columnNamesSet.add(name);
          }
        }
      }
      if (columnNamesSet.size() != axesMembers[axesIndex])
      {
        .error("ERROR: Number of names is not equal the pre-counted number.");
      }
      final List<Dimension> dimForMemberPerAxis = dimensionsForMembersPerAxis[axesIndex];
      final List<IntegermemberCntPerAxis = membersPerAxis[axesIndex];
      for (int i = 0; i < memberCntPerAxis.size(); i++)
      {
        final Integer count = memberCntPerAxis.get(i);
        final Dimension dim = dimForMemberPerAxis.get(i);
        for (int x = 0; x < count.intValue(); x += 1)
        {
          this.[dimColIndex + x] = dim;
          this.[dimColIndex + x] = axesIndex;
        }
        dimColIndex = count.intValue() + dimColIndex;
      }
      final String[] names = columnNamesSet.toArray(new String[columnNamesSet.size()]);
      System.arraycopy(names, 0, this.columnIndexnames.length);
      columnIndex += names.length;
    }
    if (. > 0)
    {
      // now create the column names for the column-axis
      final Axis axis = axes[0];
      final List<Position> positions = axis.getPositions();
      for (int i = 0; i < positions.size(); i++)
      {
        final Position position = positions.get(i);
        final StringBuffer positionName = new StringBuffer(100);
        for (int j = 0; j < position.size(); j++)
        {
          if (j != 0)
          {
            positionName.append('/');
          }
          final Member member = position.get(j);
          //positionName.append(MondrianUtil.getUniqueMemberName(member));
          positionName.append(member.getName());
        }
        [columnIndex] = positionName.toString();
        columnIndex += 1;
      }
    }
    if (. == 0)
    {
      [0] = "Measure";
    }
    if (rowLimit > 0)
    {
       = Math.min(rowLimit);
    }
  }
  public int getRowCount()
  {
    return ;
  }
  public int getColumnCount()
  {
    return ;
  }

  
Returns a default name for the column using spreadsheet conventions: A, B, C, ... Z, AA, AB, etc. If column cannot be found, returns an empty string.

Parameters:
column the column being queried
Returns:
a string containing the default name of column
  public String getColumnName(final int column)
  {
    return [column];
  }
  public Object getValueAt(final int rowIndex,
          final int columnIndex)
  {
    if (columnIndex >= .)
    {
      throw new IndexOutOfBoundsException();
    }
    final int correctedColIndex;
    if (. > 0)
    {
      final int startOfColumnIndex =  - [0];
      if (columnIndex < startOfColumnIndex)
      {
        // this is a query for a axis-header
        correctedColIndex = -1;
      }
      else
      {
        correctedColIndex = columnIndex - startOfColumnIndex;
      }
    }
    else
    {
      correctedColIndex = 0;
    }
    final int[] cellKey = computeCellKey(rowIndexcorrectedColIndex);
    // user asked for a dimension ...
    final Dimension dimension = [columnIndex];
    if (dimension == null)
    {
      final Cell cell = .getCell(cellKey);
      if (cell.isNull())
      {
        return null;
      }
      return cell.getValue();
    }
    Member contextMember = getContextMember(dimensioncolumnIndexcellKey);
    if (contextMember != null)
    {
      return contextMember.getName();
    }
    return null;
  }

  
Returns Object.class regardless of columnIndex.

Parameters:
columnIndex the column being queried
Returns:
the Object.class
  public Class<?> getColumnClass(int columnIndex)
  {
    try
    {
      Object targetClassObj = getValueAt(0, columnIndex);
      return targetClassObj == null ? Object.class : targetClassObj.getClass();
    }
    catch (Exception e)
    {
      return Object.class;
    }
  }
  private int[] computeCellKey(final int rowIndexfinal int columnIndex)
  {
    final int[] cellKey = new int[.];
    int tmpRowIdx = rowIndex;
    if (. > 0)
    {
      cellKey[0] = columnIndex;
    }
    for (int i = 1; i
            < .i++)
    {
      final int axisSize = [i];
      if (axisSize == 0)
      {
        cellKey[i] = 0;
      }
      else
      {
        final int pos = tmpRowIdx % axisSize;
        cellKey[i] = pos;
        tmpRowIdx = tmpRowIdx / axisSize;
      }
    }
    return cellKey;
  }
  private Member getContextMember(final Dimension dimension,
          final int columnIndex,
          final int[] cellKey)
  {
    final int axisIndex = [columnIndex];
    final Axis[] axes = .getAxes();
    final Axis axis = axes[axisIndex];
    final int posIndex = cellKey[axisIndex];
    final List<Position> positionList = axis.getPositions();
    if (positionList.isEmpty())
    {
      return null;
    }
    final Position position = positionList.get(posIndex);
    for (int i = 0; i
            < position.size(); i++)
    {
      final Member member = position.get(i);
      if (dimension.equals(member.getDimension()))
      {
        return member;
      }
    }
    return null;
  }
  public void close()
  {
    .close();
  }

  
Returns the meta-attribute as Java-Object. The object type that is expected by the report engine is defined in the TableMetaData property set. It is the responsibility of the implementor to map the native meta-data model into a model suitable for reporting.

Meta-data models that only describe meta-data for columns can ignore the row-parameter.

Parameters:
rowIndex the row of the cell for which the meta-data is queried.
columnIndex the index of the column for which the meta-data is queried.
Returns:
the meta-data object.
  public DataAttributes getCellDataAttributes(final int rowIndexfinal int columnIndex)
  {
    if (columnIndex >= .)
    {
      throw new IndexOutOfBoundsException();
    }
    final int[] cellKey = computeCellKey(rowIndexcolumnIndex);
    // user asked for a dimension ...
    final Dimension dimension = [columnIndex];
    if (dimension == null)
    {
      final Cell cell = .getCell(cellKey);
      return new MDXMetaDataCellAttributes(EmptyDataAttributes.INSTANCE, cell);
    }
    Member contextMember = getContextMember(dimensioncolumnIndexcellKey);
    while (contextMember != null)
    {
      if (contextMember.getLevel().getUniqueName().equals(getColumnName(columnIndex)))
      {
        return new MDXMetaDataMemberAttributes(EmptyDataAttributes.INSTANCE, contextMember);
      }
      contextMember = contextMember.getParentMember();
    }
    return EmptyDataAttributes.INSTANCE;
  }
  public boolean isCellDataAttributesSupported()
  {
    return true;
  }
  public DataAttributes getColumnAttributes(final int column)
  {
    return EmptyDataAttributes.INSTANCE;
  }

  
Returns table-wide attributes. This usually contain hints about the data-source used to query the data as well as hints on the sort-order of the data.

Returns:
the table attributes.
  public DataAttributes getTableAttributes()
  {
    final DefaultDataAttributes dataAttributes = new DefaultDataAttributes();
    dataAttributes.setMetaAttribute(MetaAttributeNames.Core.NAMESPACE,
            MetaAttributeNames.Core.CROSSTAB_MODE, DefaultConceptQueryMapper.INSTANCE, MetaAttributeNames.Core.CROSSTAB_VALUE_NORMALIZED);
    return dataAttributes;
  }
New to GrepCode? Check out our FAQ X