Skip to content

Commit

Permalink
[MONDRIAN-1581] Adding support for .getParentMember() to XmlaOlap4jSu…
Browse files Browse the repository at this point in the history
…rpriseMember.
  • Loading branch information
mkambol committed Jun 26, 2013
1 parent 1728c11 commit 35d9ba4
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 1 deletion.
59 changes: 58 additions & 1 deletion src/org/olap4j/driver/xmla/XmlaOlap4jCellSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,8 @@ private static class XmlaOlap4jSurpriseMember
private final int lnum;
private final String caption;
private final String uname;
private Member parentMember;
private final String parentMemberUniqueName;

/**
* Creates an XmlaOlap4jSurpriseMember.
Expand All @@ -1402,6 +1404,15 @@ private static class XmlaOlap4jSurpriseMember
this.lnum = lnum;
this.caption = caption;
this.uname = uname;
parentMemberUniqueName = getParentUniqueName();
}

private String getParentUniqueName() {
List<IdentifierSegment> segments = IdentifierNode
.parseIdentifier(getUniqueName()).getSegmentList();
IdentifierNode parentIdentifier = new IdentifierNode(
segments.subList(0, segments.size() - 1));
return parentIdentifier.toString();
}

public final XmlaOlap4jCube getCube() {
Expand Down Expand Up @@ -1429,8 +1440,54 @@ public int getChildMemberCount() {
return 0;
}


/**
* In the case of a query-calculated member over XMLA, the only
* information we have to determine parent is this member's own
* unique name, its level number, and whether .hasAll() is true.
*
* This method attempts to figure out the parent member based on
* what we hope is the unique name of the parent--i.e. the member's
* own unique name with the last segment stripped off.
*
* For calculated members defined directly on the hierarchy,
* stripping off the last segment does not produce a valid member
* unique name. In that case, though, the level depth is 0, which
* we can take as an indication that the parent is null.
*/
public Member getParentMember() {
return null;
if (getLevel().getDepth() == 0 || parentMemberUniqueName == null) {
return null;
}
if (parentMember == null) {
try {
parentMember =
getCube().getMetadataReader()
.lookupMemberByUniqueName(parentMemberUniqueName);
if (parentMember == null
&& getLevel().getDepth() == 1
&& getHierarchy().hasAll())
{
// couldn't find the parent by the constructed
// unique name, but we know it's (All) in this case.
parentMember = getAllMember();
}
} catch (OlapException e) {
throw new RuntimeException(
"Failed to retrieve parent of " + getName(), e);
}
}
return parentMember;
}

private Member getAllMember() throws OlapException {
if (!getHierarchy().hasAll()) {
return null;
}
List<Member> roots = getHierarchy().getRootMembers();
assert roots.size() == 1;

return roots.get(0);
}

public Level getLevel() {
Expand Down
63 changes: 63 additions & 0 deletions testsrc/org/olap4j/ConnectionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2296,6 +2296,69 @@ public void testParentChild() throws ClassNotFoundException, SQLException {
assertEquals(0, positions.get(0).getMembers().size());
}

public void testCalculatedMemberParent()
throws ClassNotFoundException, SQLException
{
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);

// map of calc member names -> expected parent
Map<String, String> tests = new HashMap<String, String>();
// on top level member of hierarchy w/o All
tests.put("Time.[1997].calc", "Time.[1997]");
// defined against the hierarchy
tests.put("[Time].[Time].[calc]", null);
// under [All]
tests.put("[Store].[All Stores].calc", "[Store].[All Stores]");
// defined using Level name
tests.put(
"[Store].[Store Country].[USA].calc",
"[Store].[All Stores].[USA]");
// parent child
tests.put(
"[Employees].[Employees].[All Employees].calc",
"[Employees].[Employees].[All Employees]");
// under [All] member of single level dimension
tests.put(
"[Pay Type].[All Pay Types].calc",
"[Pay Type].[All Pay Types]");

String mdxWith = "with member %s as '1' ";
String mdxSelect = "select {%s} on 0 from hr";
for (String calcMember : tests.keySet()) {
// Get the calc member
String calcMemberQuery = String
.format(mdxWith + mdxSelect, calcMember, calcMember);
CellSet calcCell = olapConnection.createStatement()
.executeOlapQuery(calcMemberQuery);
Member calc = calcCell.getAxes().get(0).getPositions()
.get(0).getMembers().get(0);

String parentMemberName = tests.get(calcMember);

if (parentMemberName != null) {
// Retrieve the parent member
String parentMemberQuery = String
.format(mdxSelect, parentMemberName);
CellSet parentCell = olapConnection.createStatement()
.executeOlapQuery(parentMemberQuery);

Member parent = parentCell.getAxes().get(0).getPositions()
.get(0).getMembers().get(0);
// verify parent member and calc.getParentMember() are the same
assertEquals(
"Parent member of " + calcMember + " is unexpected.",
parent, calc.getParentMember());
} else {
assertEquals(
"Expecting a null parent member for " + calcMember,
null, calc.getParentMember());
}
}
}

/**
* Tests the type-derivation for
* {@link org.olap4j.mdx.SelectNode#getFrom()} and the {@link CubeType}
Expand Down

0 comments on commit 35d9ba4

Please sign in to comment.