📄 quax.java
字号:
/**
* split Funcall to node and complement
*/
private void splitFunCall(TreeNode nFunCall, Member member, int iHier) {
Object oExp = nFunCall.getReference();
// it is possible (if the split member is of dimension to be collapsed),
// that this funcall does not contain member.
// Then - there is nothing to split.
if (!isMemberInFunCall(oExp, member, nFunCall.getLevel() - 1))
return; // nothing to split
Object oComplement = createComplement(oExp, member, iHier); // can be null
if (oComplement == null) {
// this means, that the set resolves to a single member,
// mPath[iDimNode]
nFunCall.setReference(uti.objForMember(member));
// nothing to split
return;
}
// split the Funcall
TreeNode newNodeComplement = new TreeNode(oComplement);
TreeNode newNodeMember = new TreeNode(uti.objForMember(member));
// add the children
for (Iterator iter = nFunCall.getChildren().iterator(); iter.hasNext();) {
TreeNode nChild = (TreeNode) iter.next();
newNodeComplement.addChildNode(nChild.deepCopy());
newNodeMember.addChildNode(nChild.deepCopy());
}
TreeNode nInsert = nFunCall.getParent();
nFunCall.remove();
nInsert.addChildNode(newNodeComplement);
nInsert.addChildNode(newNodeMember);
} // splitFuncall
/**
* remove Children node
*
* @param nodeToRemove
*/
private void removePathToNode(TreeNode nodeToRemove) {
if (nodeToRemove.getParent().getChildren().size() > 1) {
// this node has siblings, just remove it
nodeToRemove.remove();
} else {
// no siblings, remove the first parent node having siblings
TreeNode parent = nodeToRemove.getParent();
while (parent.getParent().getChildren().size() == 1) {
parent = parent.getParent();
}
if (parent.getLevel() > 0) // should always be true
parent.remove();
}
}
/**
* generate Exp for all nodes of dimension iDimension
*
* @param iDimension
* @return Exp for all nodes
*/
public Object genExpForDim(int iDimension) {
// if we got a generate function on this hier, preserve it
if (generateIndex >= 0 && generateIndex == iDimension && generateMode > CalcSet.SIMPLE) {
TreeNode topCountNode = (TreeNode) posTreeRoot.getChildren().get(0);
for (int i = 0; i < generateIndex; i++) {
// the path to the topcount node at generateIndex does not
// matter
List children = topCountNode.getChildren();
topCountNode = (TreeNode) children.get(0);
}
Object topcount = topCountNode.getReference();
SetExp setexp = new SetExp(generateMode, topcount, hiers[iDimension]);
return setexp;
}
List funCallList = collectFunCalls(iDimension);
List memberList = collectMembers(iDimension);
cleanupMemberList(funCallList, memberList, iDimension);
if (funCallList.size() == 0 && memberList.size() == 1)
return memberList.get(0); // single member only
Object mSet = null;
if (memberList.size() > 0) {
Object[] aExp = memberList.toArray(new Object[0]);
mSet = uti.createFunCall("{}", aExp, QuaxUti.FUNTYPE_BRACES);
}
if (funCallList.size() == 0)
return mSet;
if (funCallList.size() == 1 && mSet == null)
return funCallList.get(0);
Object set;
int start;
if (mSet != null) {
set = mSet;
start = 0;
} else {
set = funCallList.get(0);
start = 1;
}
for (int j = start; j < funCallList.size(); j++) {
set = uti.createFunCall("Union", new Object[] { set, funCallList.get(j)},
QuaxUti.FUNTYPE_FUNCTION);
}
return set;
}
/**
* create drillup expression for dimension
*
* @param iDim
* dimension to be drilled up
* @return
*/
private Object drillupExp(int iDim, Hierarchy hier) {
// the drillup logic is:
// for all members of this dimension find the deepest level.
// find the members of this deepest level
// find the grandfathers of those deepest members
// drill up goes to the children of those grandfathers.
// special cases:
// the deepest level has all members (level.members)
// the drillup goes to parent_level.members
final int[] maxLevel = new int[1];
maxLevel[0] = 0;
List drillupList = collectDrillup(iDim, maxLevel);
Object expForHier = null;
if (maxLevel[0] == 0) {
// drillup goes to top level members
// we generate an explicit member set rather than level.members
// usually, this is a single member "All xy"
expForHier = uti.topLevelMembers(hier, false);
} else {
if (drillupList.size() == 1) {
expForHier = drillupList.get(0);
} else {
// more than 1 set expression , need union
for (Iterator iter = drillupList.iterator(); iter.hasNext();) {
Object oExp = iter.next();
if (expForHier == null)
expForHier = oExp;
else {
expForHier = uti.createFunCall("Union", new Object[] { expForHier, oExp},
QuaxUti.FUNTYPE_FUNCTION);
}
}
}
}
return expForHier;
}
/**
* collect drillup Exps of dimension i
*
* @param iDim
*/
private List collectDrillup(final int iDim, final int[] maxLevel) {
final List drillupList = new ArrayList();
posTreeRoot.walkChildren(new TreeNodeCallback() {
/**
* callback collect GrandFathers of deepest for dimension workInt
*/
public int handleTreeNode(TreeNode node) {
int iDimNode = node.getLevel() - 1;
if (iDimNode < iDim)
return TreeNodeCallback.CONTINUE;
// iDimNode == workInt
Object oExp = node.getReference();
if (!uti.isMember(oExp)) {
// FunCall
addFunCallToDrillup(drillupList, oExp, maxLevel);
} else {
// member
Member m = uti.memberForObj(oExp);
uti.addMemberUncles(drillupList, m, maxLevel);
} // member
return TreeNodeCallback.CONTINUE_SIBLING;
} // handlePositionTreeNode
});
return drillupList;
}
/**
* collect Funcalls of dimension iDim
*
* @param iDim
*/
private List collectFunCalls(final int iDim) {
if (posTreeRoot == null)
return Collections.EMPTY_LIST;
final List funCallList = new ArrayList();
posTreeRoot.walkChildren(new TreeNodeCallback() {
/**
* callback collect Funcalls of dimension workInt
*/
public int handleTreeNode(TreeNode node) {
int iDimNode = node.getLevel() - 1;
if (iDimNode < iDim)
return TreeNodeCallback.CONTINUE;
// iDimNode == workInt
Object oExp = node.getReference();
if (!uti.isMember(oExp)) {
// FunCall
// need unique representation in order to avoid doubles
String unique = uti.funString(oExp).toString();
if (!funCallList.contains(unique)) {
funCallList.add(oExp);
funCallList.add(unique);
}
}
return TreeNodeCallback.CONTINUE_SIBLING;
} // handlePositionTreeNode
});
// remove the unique strings, which were just added to avoid doubles
for (Iterator iter = funCallList.iterator(); iter.hasNext();) {
Object element = iter.next();
if (element instanceof String)
iter.remove();
}
return funCallList;
}
/**
* remove members from member list being in FunCall list
*
* @param funCallList
* @param memberList
*/
private void cleanupMemberList(List funCallList, List memberList, int iDim) {
if (funCallList.size() > 0 && memberList.size() > 0) {
MemberLoop: for (Iterator itMem = memberList.iterator(); itMem.hasNext();) {
Object oMember = itMem.next();
Member m = uti.memberForObj(oMember);
for (Iterator itFun = funCallList.iterator(); itFun.hasNext();) {
Object oFun = itFun.next();
if (isMemberInFunCall(oFun, m, iDim)) {
itMem.remove();
continue MemberLoop;
}
}
} // MemberLoop
}
}
/**
* collect Members of dimension iDim
*
* @param iDim
* @param fList
*/
List collectMembers(final int iDim) {
if (posTreeRoot == null)
return Collections.EMPTY_LIST;
final List memberList = new ArrayList();
posTreeRoot.walkChildren(new TreeNodeCallback() {
/**
* callback collect Funcalls of dimension workInt
*/
public int handleTreeNode(TreeNode node) {
int iDimNode = node.getLevel() - 1;
if (iDimNode < iDim)
return TreeNodeCallback.CONTINUE;
// iDimNode == workInt
Object oExp = node.getReference();
if (uti.isMember(oExp) && !memberList.contains(oExp))
memberList.add(oExp);
return TreeNodeCallback.CONTINUE_SIBLING;
} // handlePositionTreeNode
});
return memberList;
}
/**
* add a Funcall to Drillup list
*
* @param f
*/
private void addFunCallToDrillup(List list, Object oFun, int[] maxLevel) {
if (uti.isFunCallTo(oFun, "Union")) {
for (int i = 0; i < 2; i++) {
Object fExp = uti.funCallArg(oFun, i);
addFunCallToDrillup(list, fExp, maxLevel);
}
} else if (uti.isFunCallTo(oFun, "{}")) {
// set of members
for (int i = 0; i < uti.funCallArgCount(oFun); i++) {
Object oMember = uti.funCallArg(oFun, i);
Member m = uti.memberForObj(oMember);
uti.addMemberUncles(list, m, maxLevel);
}
} else if (uti.isFunCallTo(oFun, "Children")) {
Object oMember = uti.funCallArg(oFun, 0);
Member m = uti.memberForObj(oMember);
uti.addMemberSiblings(list, m, maxLevel);
} else if (uti.isFunCallTo(oFun, "Descendants")) {
Object oMember = uti.funCallArg(oFun, 0);
Member m = uti.memberForObj(oMember);
Object oLevel = uti.funCallArg(oFun, 1);
Level lev = uti.LevelForObj(oLevel);
int level = uti.levelDepthForMember(m);
int levlev = ((MDXLevel) lev).getDepth();
if (levlev == level + 1)
uti.addMemberSiblings(list, m, maxLevel); // same as children
else if (levlev == level + 2)
uti.addMemberChildren(list, m, maxLevel); // m *is* grandfather
else {
// add descendants of parent level
Level parentLevel = uti.getParentLevel(lev);
uti.addMemberDescendants(list, m, parentLevel, maxLevel);
}
} else if (uti.isFunCallTo(oFun, "Members")) {
// add parent level members
Object oLevel = uti.funCallArg(oFun, 0);
Level lev = uti.LevelForObj(oLevel);
int levlev = ((MDXLevel) lev).getDepth();
if (levlev == 0)
return; // cannot drill up
Level parentLevel = uti.getParentLevel(lev);
uti.addLevelMembers(list, parentLevel, maxLevel);
} else {
// must be Top/Bottom Function with arg[0] being base set
Object oFun2 = uti.funCallArg(oFun, 0);
addFunCallToDrillup(list, oFun2, maxLevel); // do not have a better
// solution
}
}
/**
* add FunCall to list
*
* @param f
* @param list
*/
private void funToList(Object oFun, List list) {
if (uti.isFunCallTo(oFun, "Union")) {
Object oArg0 = uti.funCallArg(oFun, 0);
Object oArg1 = uti.funCallArg(oFun, 1);
funToList(oArg0, list);
funToList(oArg1, list);
} else if (uti.isFunCallTo(oFun, "{}")) {
for (int i = 0; i < uti.funCallArgCount(oFun); i++) {
// member sets are resolved to single members
Object oMember = uti.funCallArg(oFun, i);
list.add(oMember);
}
} else {
list.add(oFun);
}
}
// ==========
// Utility
// ==========
/**
* hierarchize the query axis position array
*/
// this code is not working
public void hierarchizePositions(final Member[][] aPosMem) {
final int nDimension = aPosMem[0].length;
final Map[] firstOccurrences = new HashMap[nDimension];
for (int i = 0; i < nDimension; i++) {
firstOccurrences[i] = new HashMap();
}
for (int i = 0; i < aPosMem.length; i++) {
for (int j = 0; j < nDimension; j++) {
// String uName = aPosMem[i][j].getUniqueName();
if (!firstOccurrences[j].containsKey(aPosMem[i][j])) {
firstOccurrences[j].put(aPosMem[i][j], new Integer(i));
}
} // j
} //i
Arrays.sort(aPosMem, new Comparator() {
public int compare(Object o1, Object o2) {
// compare two position member arrays
Member[] a1 = (Member[]) o1;
Member[] a2 = (Member[]) o2;
DimensionLoop: for (int i = 0; i < a1.length; i++) {
if (a1[i].equals(a2[i]))
continue DimensionLoop;
// first difference at dimension index i
// if it is on different level, the descendant is higher
// otherwise - decide by first occurrence
int level1 = ((MDXLevel) a1[i].getLevel()).getDepth();
int level2 = ((MDXLevel) a1[i].getLevel()).getDepth();
if (level1 == level2) {
int first1 = ((Integer) firstOccurrences[i].get(a1[i])).intValu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -