Skip to content

Commit

Permalink
MONDRIAN: Add LEAVES flag to DESCENDANTS function.
Browse files Browse the repository at this point in the history
[git-p4: depot-paths = "//open/mondrian/": change = 4440]
  • Loading branch information
julianhyde committed Nov 20, 2005
1 parent 3fdf59a commit ec6e649
Show file tree
Hide file tree
Showing 13 changed files with 495 additions and 171 deletions.
12 changes: 12 additions & 0 deletions demo/FoodMart.xml
Expand Up @@ -472,6 +472,18 @@ fullname
</Hierarchy>
</Dimension>

<Dimension name="Geography" foreignKey="store_id">
<Hierarchy hasAll="true" primaryKey="store_id">
<Table name="store_ragged"/>
<Level name="Country" column="store_country" uniqueMembers="true"
hideMemberIf="Never"/>
<Level name="State" column="store_state" uniqueMembers="true"
hideMemberIf="IfParentsName"/>
<Level name="City" column="store_city" uniqueMembers="false"
hideMemberIf="IfBlankName"/>
</Hierarchy>
</Dimension>

<DimensionUsage name="Store Size in SQFT" source="Store Size in SQFT"
foreignKey="store_id"/>
<DimensionUsage name="Store Type" source="Store Type" foreignKey="store_id"/>
Expand Down
9 changes: 5 additions & 4 deletions src/main/mondrian/olap/DelegatingSchemaReader.java
Expand Up @@ -51,10 +51,11 @@ public Member[] getMemberChildren(Member[] members) {
return schemaReader.getMemberChildren(members);
}

public void getMemberDescendants(Member member, List result, Level level,
boolean before, boolean self, boolean after) {
schemaReader.getMemberDescendants(member, result, level,
before, self, after);
public void getMemberDescendants(
Member member, List result, Level level,
boolean before, boolean self, boolean after, boolean leaves) {
schemaReader.getMemberDescendants(
member, result, level, before, self, after, leaves);
}

public int getMemberDepth(Member member) {
Expand Down
7 changes: 5 additions & 2 deletions src/main/mondrian/olap/SchemaReader.java
Expand Up @@ -85,9 +85,12 @@ public interface SchemaReader {
* @param before Whether to output members above <code>level</code>
* @param self Whether to output members at <code>level</code>
* @param after Whether to output members below <code>level</code>
* @param leaves Whether to output members which are leaves
*/
void getMemberDescendants(Member member, List result, Level level,
boolean before, boolean self, boolean after);
void getMemberDescendants(
Member member, List result, Level level,
boolean before, boolean self, boolean after, boolean leaves);

/**
* Returns the depth of a member.
*
Expand Down
109 changes: 70 additions & 39 deletions src/main/mondrian/olap/fun/DescendantsFunDef.java
Expand Up @@ -10,7 +10,7 @@
package mondrian.olap.fun;

import mondrian.olap.*;
import mondrian.resource.MondrianResource;
import mondrian.olap.type.NumericType;

import java.util.List;
import java.util.ArrayList;
Expand All @@ -23,50 +23,59 @@ class DescendantsFunDef extends FunDefBase {
private final boolean before;
private final boolean after;
private final boolean depthSpecified;
private final int depthLimit;
private final boolean leaves;

public DescendantsFunDef(
FunDef dummyFunDef,
int flag,
boolean depthSpecified,
int depthLimit) {
boolean depthSpecified) {
super(dummyFunDef);

this.self = FunUtil.checkFlag(flag, Flags.SELF, true);
this.after = FunUtil.checkFlag(flag, Flags.AFTER, true);
this.before = FunUtil.checkFlag(flag, Flags.BEFORE, true);
// leaves = FunUtil.checkFlag(flag, Flags.LEAVES, true);
this.leaves = FunUtil.checkFlag(flag, Flags.LEAVES, true);
this.depthSpecified = depthSpecified;
this.depthLimit = depthLimit;
}

public Object evaluate(Evaluator evaluator, Exp[] args) {
Member member = getMemberArg(evaluator, args, 0, true);
List result = new ArrayList();
final SchemaReader schemaReader = evaluator.getSchemaReader();
if (depthSpecified) {
descendantsByDepth(member, result, schemaReader,
depthLimit, before, self, after);
int depthLimit = getIntArg(evaluator, args, 1);
if (leaves) {
if (depthLimit < 0) {
depthLimit = Integer.MAX_VALUE;
}
descendantsLeavesByDepth(
member, result, schemaReader, depthLimit);
} else {
descendantsByDepth(
member, result, schemaReader,
depthLimit, before, self, after);
}
} else {
final Level level = args.length > 1
? getLevelArg(evaluator, args, 1, true)
: member.getLevel();
schemaReader.getMemberDescendants(member, result,
level, before, self, after);
schemaReader.getMemberDescendants(
member, result, level, before, self, after, leaves);
}

hierarchize(result, false);

return result;
}

private static void descendantsByDepth(Member member,
List result,
final SchemaReader schemaReader,
final int depthLimitFinal,
final boolean before,
final boolean self,
final boolean after) {
private static void descendantsByDepth(
Member member,
List result,
final SchemaReader schemaReader,
final int depthLimitFinal,
final boolean before,
final boolean self,
final boolean after) {
Member[] children = {member};
for (int depth = 0;; ++depth) {
if (depth == depthLimitFinal) {
Expand Down Expand Up @@ -95,6 +104,40 @@ private static void descendantsByDepth(Member member,
}
}

private static void descendantsLeavesByDepth(
Member member,
List result,
final SchemaReader schemaReader,
final int depthLimit) {
if (!schemaReader.isDrillable(member)) {
if (depthLimit >= 0) {
result.add(member);
}
return;
}
Member[] children = {member};
for (int depth = 0; depth <= depthLimit; ++depth) {
children = schemaReader.getMemberChildren(children);
if (children.length == 0) {
throw Util.newInternal("drillable member must have children");
}
List nextChildren = new ArrayList();
for (int i = 0; i < children.length; i++) {
Member child = children[i];
if (schemaReader.isDrillable(child)) {
nextChildren.add(child);
} else {
result.add(child);
}
}
if (nextChildren.isEmpty()) {
break;
}
children = (Member[])
nextChildren.toArray(new Member[nextChildren.size()]);
}
}

/**
* Enumeration of the flags allowed to the <code>DESCENDANTS</code>
* function.
Expand Down Expand Up @@ -134,43 +177,31 @@ public Resolver() {
}

protected FunDef createFunDef(Exp[] args, FunDef dummyFunDef) {
int depthLimit = -1; // unlimited
boolean depthSpecified = false;
int flag = Flags.SELF;
if (args.length == 1) {
depthLimit = -1;
flag = Flags.SELF_BEFORE_AFTER;
}
final boolean depthSpecified;
if (args.length >= 2) {
if (args[1] instanceof Literal) {
Literal literal = (Literal) args[1];
if (literal.getValue() instanceof Number) {
Number number = (Number) literal.getValue();
depthLimit = number.intValue();
depthSpecified = true;
}
}
depthSpecified = args[1].getTypeX() instanceof NumericType;
} else {
depthSpecified = false;
}
if (args.length >= 3) {
flag = FunUtil.getLiteralArg(args, 2, Flags.SELF,
Flags.instance, dummyFunDef);
}

if (FunUtil.checkFlag(flag, Flags.LEAVES, true)) {
// LEAVES isn't supported
throw MondrianResource.instance().LeavesNotSupported.ex();
}
final int depthLimitFinal = depthLimit < 0
? Integer.MAX_VALUE
: depthLimit;
final int flagFinal = flag;
final boolean depthSpecifiedFinal = depthSpecified;
return new DescendantsFunDef(dummyFunDef, flagFinal,
depthSpecifiedFinal, depthLimitFinal);
return new DescendantsFunDef(
dummyFunDef,
flag,
depthSpecified);
}

public String[] getReservedWords() {
return Flags.instance.getNames();
}
}
}

// End DescendantsFunDef.java
30 changes: 16 additions & 14 deletions src/main/mondrian/rolap/CacheMemberReader.java
Expand Up @@ -98,7 +98,7 @@ public boolean hasLevelMembers(RolapLevel level) {
return false;
}

public RolapMember lookupMember(String[] uniqueNameParts,
public RolapMember lookupMember(String[] uniqueNameParts,
boolean failIfNotFound) {
return RolapUtil.lookupMember(this, uniqueNameParts, failIfNotFound);
}
Expand All @@ -113,8 +113,8 @@ public List getRootMembers() {
return list;
}

public List getMembersInLevel(RolapLevel level,
int startOrdinal,
public List getMembersInLevel(RolapLevel level,
int startOrdinal,
int endOrdinal) {
List list = new ArrayList();
int levelDepth = level.getDepth();
Expand Down Expand Up @@ -171,8 +171,8 @@ public RolapMember getLeadMember(RolapMember member, int n) {
}
}

public void getMemberRange(RolapLevel level,
RolapMember startMember,
public void getMemberRange(RolapLevel level,
RolapMember startMember,
RolapMember endMember,
List list) {
Util.assertPrecondition(startMember != null, "startMember != null");
Expand All @@ -195,7 +195,7 @@ public int compare(RolapMember m1, RolapMember m2, boolean siblingsAreEqual) {
if (m1 == m2) {
return 0;
}
if (siblingsAreEqual &&
if (siblingsAreEqual &&
(m1.getParentMember() == m2.getParentMember())) {
return 0;
}
Expand All @@ -205,14 +205,16 @@ public int compare(RolapMember m1, RolapMember m2, boolean siblingsAreEqual) {
return (m1.getOrdinal() < m2.getOrdinal()) ? -1 : 1;
}

public void getMemberDescendants(RolapMember member,
List result,
RolapLevel level,
boolean before,
boolean self,
boolean after) {
RolapUtil.getMemberDescendants(this, member, level, result, before,
self, after);
public void getMemberDescendants(
RolapMember member,
List result,
RolapLevel level,
boolean before,
boolean self,
boolean after,
boolean leaves) {
RolapUtil.getMemberDescendants(
this, member, level, result, before, self, after, leaves);
}

}
Expand Down
28 changes: 15 additions & 13 deletions src/main/mondrian/rolap/DelegatingMemberReader.java
Expand Up @@ -32,15 +32,15 @@ public RolapMember getLeadMember(RolapMember member, int n) {
return memberReader.getLeadMember(member, n);
}

public List getMembersInLevel(RolapLevel level,
int startOrdinal,
public List getMembersInLevel(RolapLevel level,
int startOrdinal,
int endOrdinal) {
return memberReader.getMembersInLevel(level, startOrdinal, endOrdinal);
}

public void getMemberRange(RolapLevel level,
public void getMemberRange(RolapLevel level,
RolapMember startMember,
RolapMember endMember,
RolapMember endMember,
List list) {
memberReader.getMemberRange(level, startMember, endMember, list);
}
Expand All @@ -49,14 +49,16 @@ public int compare(RolapMember m1, RolapMember m2, boolean siblingsAreEqual) {
return memberReader.compare(m1, m2, siblingsAreEqual);
}

public void getMemberDescendants(RolapMember member,
List result,
RolapLevel level,
boolean before,
boolean self,
boolean after) {
memberReader.getMemberDescendants(member, result, level, before, self,
after);
public void getMemberDescendants(
RolapMember member,
List result,
RolapLevel level,
boolean before,
boolean self,
boolean after,
boolean leaves) {
memberReader.getMemberDescendants(
member, result, level, before, self, after, leaves);
}

public RolapHierarchy getHierarchy() {
Expand Down Expand Up @@ -87,7 +89,7 @@ public int getMemberCount() {
return memberReader.getMemberCount();
}

public RolapMember lookupMember(String[] uniqueNameParts,
public RolapMember lookupMember(String[] uniqueNameParts,
boolean failIfNotFound) {
return memberReader.lookupMember(uniqueNameParts, failIfNotFound);
}
Expand Down
11 changes: 9 additions & 2 deletions src/main/mondrian/rolap/MemberReader.java
Expand Up @@ -75,9 +75,16 @@ void getMemberRange(RolapLevel level, RolapMember startMember,
* @param before Whether to output members above <code>level</code>
* @param self Whether to output members at <code>level</code>
* @param after Whether to output members below <code>level</code>
* @param leaves Whether to output members which are leaves
*/
void getMemberDescendants(RolapMember member, List result,
RolapLevel level, boolean before, boolean self, boolean after);
void getMemberDescendants(
RolapMember member,
List result,
RolapLevel level,
boolean before,
boolean self,
boolean after,
boolean leaves);
}

// End MemberReader.java

0 comments on commit ec6e649

Please sign in to comment.