Skip to content

Instantly share code, notes, and snippets.

@mysticfall
Created November 10, 2013 04:16
Show Gist options
  • Save mysticfall/4e7eba3f129c49152669 to your computer and use it in GitHub Desktop.
Save mysticfall/4e7eba3f129c49152669 to your computer and use it in GitHub Desktop.
Attempt to fix #116. It's not working as it is, because the quax doesn't provide any information about functions at the time of the invocation.
public class PlaceMembersOnAxesImpl extends AbstractTransform implements
PlaceMembersOnAxes {
/**
* @see com.eyeq.pivot4j.transform.PlaceMembersOnAxes#placeMembers(org.olap4j.metadata.Hierarchy,
* java.util.List)
*/
@Override
public void placeMembers(Hierarchy hierarchy, List<Member> members) {
QueryAdapter adapter = getQueryAdapter();
Quax quax = adapter.findQuax(hierarchy.getDimension());
if (quax == null) {
throw new IllegalArgumentException(
"Cannot find the specified hierarchy on any axis.");
}
// First, check to see if all the hierarchies have only the default
// members and the .Children functions. In that case, we try to preserve
// them instead of adding only visible members (#116).
List<Hierarchy> hierarchies = quax.getHierarchies();
Map<Hierarchy, SelectionChecker> checkers = new HashMap<Hierarchy, SelectionChecker>(
hierarchies.size());
for (Hierarchy hier : hierarchies) {
if (!OlapUtils.equals(hier, hierarchy)) {
SelectionChecker checker = new SelectionChecker(hier);
quax.getPosTreeRoot().walkTree(checker);
if (checker.getAllMember() != null) {
checkers.put(hierarchy, checker);
}
}
}
OlapUtils utils = new OlapUtils(getModel().getCube());
List<Exp> expressions = new ArrayList<Exp>(hierarchies.size());
for (Hierarchy hier : hierarchies) {
SelectionChecker checker = checkers.get(hier);
boolean targetHierarchy = OlapUtils.equals(hier, hierarchy);
if (checker == null) {
List<Member> selection;
if (targetHierarchy) {
selection = members;
} else {
selection = findVisibleMembers(hier);
}
List<Exp> sets = new ArrayList<Exp>(selection.size());
if (selection.size() == 1) {
expressions.add(new MemberExp(utils
.wrapRaggedIfNecessary(selection.get(0))));
} else {
for (Member member : selection) {
sets.add(new MemberExp(utils
.wrapRaggedIfNecessary(member)));
}
expressions.add(new FunCall("{}", Syntax.Braces, sets));
}
} else if (checker.isExpanded()) {
Member wrap = utils.wrapRaggedIfNecessary(checker
.getAllMember());
FunCall set = new FunCall("{}", Syntax.Braces);
FunCall children = new FunCall("Children", Syntax.Property);
children.getArgs().add(new MemberExp(wrap));
set.getArgs().add(new MemberExp(wrap));
set.getArgs().add(children);
expressions.add(set);
} else {
expressions.add(new MemberExp(utils
.wrapRaggedIfNecessary(checker.getAllMember())));
}
}
// generate the crossjoins
quax.regeneratePosTree(expressions, false);
if (logger.isDebugEnabled()) {
logger.debug("setQueryAxis axis={}, nDimension={}",
quax.getOrdinal(), hierarchies.size());
logger.debug("Expression for the axis : {}", quax);
}
}
class SelectionChecker implements TreeNodeCallback<Exp> {
private QuaxUtil util = new QuaxUtil(getModel().getCube());
private Hierarchy hierarchy;
private Member allMember;
private int allMemberCount = 0;
private int expandedCount = 0;
private boolean hasSelection = false;
/**
* @param hierarchy
*/
SelectionChecker(Hierarchy hierarchy) {
if (hierarchy == null) {
throw new NullArgumentException("hierarchy");
}
this.hierarchy = hierarchy;
}
/**
* @see com.eyeq.pivot4j.util.TreeNodeCallback#handleTreeNode(com.eyeq.pivot4j.util.TreeNode)
*/
@Override
public int handleTreeNode(TreeNode<Exp> node) {
Exp exp = node.getReference();
if (exp != null) {
checkExp(exp);
}
if (hasSelection) {
return BREAK;
}
return CONTINUE;
}
void checkExp(Exp exp) {
if (util.isMember(exp)) {
checkMember(util.memberForExp(exp));
} else if (util.isFunCallTo(exp, "{}")
|| util.isFunCallTo(exp, "CrossJoin")
|| util.isFunCallTo(exp, "Hierarchize")
|| util.isFunCallTo(exp, "Union")) {
FunCall func = (FunCall) exp;
for (Exp arg : func.getArgs()) {
checkExp(arg);
}
} else if (util.isFunCallTo(exp, "Children")) {
Member parent = util.memberForExp(util.funCallArg(exp, 0));
if (OlapUtils.equals(hierarchy, parent.getHierarchy())) {
this.expandedCount++;
}
}
}
void checkMember(Member member) {
if (OlapUtils.equals(hierarchy, member.getHierarchy())) {
if (member.isAll()) {
this.allMember = member;
this.allMemberCount++;
} else {
this.allMember = null;
this.hasSelection = true;
}
}
}
/**
* @return the allMember
*/
public Member getAllMember() {
return allMember;
}
/**
* @return the expanded
*/
public boolean isExpanded() {
return allMemberCount == expandedCount;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment