Skip to content

Commit

Permalink
Add support for MeasureGroups.
Browse files Browse the repository at this point in the history
  • Loading branch information
Fernando Arbeiza committed Feb 8, 2013
1 parent 9ec9e56 commit 0ab8655
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 0 deletions.
100 changes: 100 additions & 0 deletions src/org/olap4j/driver/xmla/XmlaOlap4jConnection.java
Expand Up @@ -1287,6 +1287,86 @@ public void handle(
}
}

static class MeasureGroupHandler extends HandlerImpl<XmlaOlap4jMeasureGroup> {
public void handle(
Element row,
Context context,
List<XmlaOlap4jMeasureGroup> list)
throws OlapException
{
// Example:
//
// <row>
// <CATALOG_NAME>FoodMart</CATALOG_NAME>
// <SCHEMA_NAME>FoodMart</SCHEMA_NAME>
// <CUBE_NAME>Sales</CUBE_NAME>
// <MEASUREGROUP_NAME>Internet Sales</MEASUREGROUP_NAME>
// <DESCRIPTION>Sales Cube - Internet Sales</DESCRIPTION>
// <IS_WRITE_ENABLED>false</IS_WRITE_ENABLED>
// <MEASUREGROUP_CAPTION>Internet Sales</MEASUREGROUP_CAPTION>
// </row>
// Unused: CATALOG_NAME, SCHEMA_NAME, CUBE_NAME, IS_WRITE_ENABLED
String measureGroupName = stringElement(row, "MEASUREGROUP_NAME");
String caption = stringElement(row, "MEASUREGROUP_CAPTION");
if (caption == null) {
caption = measureGroupName;
}
String description = stringElement(row, "DESCRIPTION");
XmlaOlap4jMeasureGroup measureGroup =
new XmlaOlap4jMeasureGroup(
context.olap4jCube,
measureGroupName,
caption,
description);
list.add(measureGroup);
}
}

static class MeasureGroupDimensionHandler extends HandlerImpl<XmlaOlap4jDimension> {
private final XmlaOlap4jCube cubeForCallback;

public MeasureGroupDimensionHandler(XmlaOlap4jCube cube) {
this.cubeForCallback = cube;
}

public void handle(
Element row,
Context context,
List<XmlaOlap4jDimension> list)
{
// Example:
//
// <row>
// <CATALOG_NAME>FoodMart</CATALOG_NAME>
// <SCHEMA_NAME>FoodMart</SCHEMA_NAME>
// <CUBE_NAME>Sales</CUBE_NAME>
// <MEASUREGROUP_NAME>Internet Sales</MEASUREGROUP_NAME>
// <MEASUREGROUP_CARDINALITY>one</MEASUREGROUP_CARDINALITY>
// <DIMENSION_UNIQUE_NAME>[Department]</DIMENSION_UNIQUE_NAME>
// <DIMENSION_CARDINALITY>one</DIMENSION_CARDINALITY>
// <DIMENSION_IS_VISIBLE>true</DIMENSION_IS_VISIBLE>
// <DIMENSION_IS_FACT_DIMENSION>false</DIMENSION_IS_FACT_DIMENSION>
// <DIMENSION_PATH>???</DIMENSION_PATH>
// <DIMENSION_GRANULARITY>???</DIMENSION_GRANULARITY>
// </row>
// Unused: CATALOG_NAME, SCHEMA_NAME, CUBE_NAME, MEASUREGROUP_NAME,
// MEASUREGROUP_CARDINALITY, DIMENSION_CARDINALITY,
// DIMENSION_IS_VISIBLE, DIMENSION_IS_VISIBLE,
// DIMENSION_IS_FACT_DIMENSION, DIMENSION_PATH,
// DIMENSION_GRANULARITY
String dimensionUniqueName =
stringElement(row, "DIMENSION_UNIQUE_NAME");
// Cannot use cubeForCallback.dimensionsByUname because it may not
// be fully populated
for (XmlaOlap4jDimension dimension : cubeForCallback.dimensions) {
if (dimension.getUniqueName().equals(dimensionUniqueName)) {
list.add(dimension);
break;
}
}
}
}

static class DimensionHandler extends HandlerImpl<XmlaOlap4jDimension> {
private final XmlaOlap4jCube cubeForCallback;

Expand Down Expand Up @@ -2306,6 +2386,26 @@ enum MetadataRequest {
new MetadataColumn("LEVEL_UNIQUE_SETTINGS"),
new MetadataColumn("LEVEL_IS_VISIBLE"),
new MetadataColumn("DESCRIPTION")),
MDSCHEMA_MEASUREGROUP_DIMENSIONS(
new MetadataColumn("CATALOG_NAME"),
new MetadataColumn("SCHEMA_NAME"),
new MetadataColumn("CUBE_NAME"),
new MetadataColumn("MEASUREGROUP_NAME"),
new MetadataColumn("MEASUREGROUP_CARDINALITY"),
new MetadataColumn("DIMENSION_UNIQUE_NAME"),
new MetadataColumn("DIMENSION_CARDINALITY"),
new MetadataColumn("DIMENSION_IS_VISIBLE"),
new MetadataColumn("DIMENSION_IS_FACT_DIMENSION"),
new MetadataColumn("DIMENSION_PATH"),
new MetadataColumn("DIMENSION_GRANULARITY")),
MDSCHEMA_MEASUREGROUPS(
new MetadataColumn("CATALOG_NAME"),
new MetadataColumn("SCHEMA_NAME"),
new MetadataColumn("CUBE_NAME"),
new MetadataColumn("MEASUREGROUP_NAME"),
new MetadataColumn("DESCRIPTION"),
new MetadataColumn("IS_WRITE_ENABLED"),
new MetadataColumn("MEASUREGROUP_CAPTION")),
MDSCHEMA_MEASURES(
new MetadataColumn("CATALOG_NAME"),
new MetadataColumn("SCHEMA_NAME"),
Expand Down
18 changes: 18 additions & 0 deletions src/org/olap4j/driver/xmla/XmlaOlap4jCube.java
Expand Up @@ -47,6 +47,8 @@ class XmlaOlap4jCube implements Cube, Named
new HashMap<String, XmlaOlap4jHierarchy>();
final Map<String, XmlaOlap4jLevel> levelsByUname =
new HashMap<String, XmlaOlap4jLevel>();
final NamedList<XmlaOlap4jMeasureGroup> measureGroups =
new NamedListImpl<XmlaOlap4jMeasureGroup>();
final List<XmlaOlap4jMeasure> measures =
new ArrayList<XmlaOlap4jMeasure>();
private final NamedList<XmlaOlap4jNamedSet> namedSets;
Expand Down Expand Up @@ -107,6 +109,18 @@ class XmlaOlap4jCube implements Cube, Named
restrictions);

// populate measures up front; a measure is needed in every query
try {
olap4jConnection.populateList(
measureGroups,
context,
XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_MEASUREGROUPS,
new XmlaOlap4jConnection.MeasureGroupHandler(),
restrictions);
} catch (OlapException e) {
// Maybe the server does not support measure groups (Mondrian)
// Just ignore the exception and do nothing
}

olap4jConnection.populateList(
measures,
context,
Expand Down Expand Up @@ -149,6 +163,10 @@ public boolean isVisible() {
return true;
}

public NamedList<MeasureGroup> getMeasureGroups() {
return Olap4jUtil.cast(measureGroups);
}

public NamedList<Dimension> getDimensions() {
return Olap4jUtil.cast(dimensions);
}
Expand Down
117 changes: 117 additions & 0 deletions src/org/olap4j/driver/xmla/XmlaOlap4jMeasureGroup.java
@@ -0,0 +1,117 @@
package org.olap4j.driver.xmla;

import java.util.ArrayList;
import java.util.List;

import org.olap4j.OlapException;
import org.olap4j.impl.Named;
import org.olap4j.impl.NamedListImpl;
import org.olap4j.impl.Olap4jUtil;
import org.olap4j.metadata.Dimension;
import org.olap4j.metadata.Hierarchy;
import org.olap4j.metadata.Measure;
import org.olap4j.metadata.MeasureGroup;
import org.olap4j.metadata.NamedList;

/**
* Implementation of {@link org.olap4j.metadata.Measure}
* for XML/A providers.
*/
class XmlaOlap4jMeasureGroup
implements MeasureGroup, Named
{
final XmlaOlap4jCube olap4jCube;
private final String name;
private final String caption;
private final String description;

final NamedList<XmlaOlap4jDimension> dimensions;
private NamedList<XmlaOlap4jHierarchy> hierarchies = null;
final List<XmlaOlap4jMeasure> measures =
new ArrayList<XmlaOlap4jMeasure>();

XmlaOlap4jMeasureGroup(
XmlaOlap4jCube olap4jCube,
String name,
String caption,
String description) throws OlapException
{
assert olap4jCube != null;
this.olap4jCube = olap4jCube;
this.name = name;
this.caption = caption;
this.description = description;

final XmlaOlap4jConnection olap4jConnection =
olap4jCube.olap4jSchema.olap4jCatalog.olap4jDatabaseMetaData.olap4jConnection;

final XmlaOlap4jConnection.Context context =
new XmlaOlap4jConnection.Context(olap4jCube, null, null, null);

String[] restrictions = {
"CATALOG_NAME",
olap4jCube.olap4jSchema.olap4jCatalog.getName(),
"SCHEMA_NAME",
olap4jCube.olap4jSchema.getName(),
"CUBE_NAME",
olap4jCube.getName(),
"MEASUREGROUP_NAME",
getName()
};

this.dimensions = new DeferredNamedListImpl<XmlaOlap4jDimension>(
XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_MEASUREGROUP_DIMENSIONS,
context,
new XmlaOlap4jConnection.MeasureGroupDimensionHandler(olap4jCube),
restrictions);

// populate measures up front; a measure is needed in every query
olap4jConnection.populateList(
measures,
context,
XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_MEASURES,
new XmlaOlap4jConnection.MeasureHandler(),
restrictions);
}

public String getName() {
return name;
}

public String getUniqueName() {
return "[" + name + "]";
}

public String getCaption() {
return caption;
}

public String getDescription() {
return description;
}

public boolean isVisible() {
return true;
}

public NamedList<Dimension> getDimensions() {
return Olap4jUtil.cast(dimensions);
}

public NamedList<Hierarchy> getHierarchies() {
// This is a costly operation. It forces the init
// of all dimensions and all hierarchies.
// We defer it to this point.
if (this.hierarchies == null) {
this.hierarchies = new NamedListImpl<XmlaOlap4jHierarchy>();
for (XmlaOlap4jDimension dim : this.dimensions) {
this.hierarchies.addAll(dim.hierarchies);
}
}
return Olap4jUtil.cast(hierarchies);
}

public List<Measure> getMeasures() {
return Olap4jUtil.cast(measures);
}
}
7 changes: 7 additions & 0 deletions src/org/olap4j/metadata/Cube.java
Expand Up @@ -66,6 +66,13 @@ public interface Cube extends MetadataElement {
*/
NamedList<Hierarchy> getHierarchies();

/**
* Returns a list of {@link MeasureGroup} objects in this Cube.
*
* @return list of MeasureGroups
*/
NamedList<MeasureGroup> getMeasureGroups();

/**
* Returns a list of {@link Measure} objects in this Cube.
*
Expand Down
11 changes: 11 additions & 0 deletions src/org/olap4j/metadata/MeasureGroup.java
@@ -0,0 +1,11 @@
package org.olap4j.metadata;

import java.util.List;

public interface MeasureGroup extends MetadataElement {
NamedList<Dimension> getDimensions();

NamedList<Hierarchy> getHierarchies();

List<Measure> getMeasures();
}

1 comment on commit 0ab8655

@julianhyde
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, I'm starting work on olap4j 2.0 and measure groups are a big part of that. Would you like to help out?

Please sign in to comment.