📄 quax.java
字号:
if (findChildrenCall(uti.funCallArg(oExp, i), level + 1))
return true;
}
return false;
}
// ==========
// Expand
// ==========
/**
* check, whether a member in a specific position path can be expanded
*
* @param pathMembers
* position path to be expanded
*/
public boolean canExpand(Member[] pathMembers) {
int iDim = pathMembers.length - 1;
// we only allow expand / collapse for a dimension
// left of a "sticky topcount"
if (!allowNavigate(iDim, false))
return false;
// first check the cache
List li = Arrays.asList(pathMembers);
if (canExpandPosMap.containsKey(li)) {
Boolean bCanExpand = (Boolean) canExpandPosMap.get(li);
return bCanExpand.booleanValue();
}
// loop over Position Tree
// reject expansion, if the axis already contains child-positions
boolean childFound = checkChildPosition(pathMembers);
// cache the result
Boolean bool = new Boolean(!childFound);
canExpandPosMap.put(li, bool);
return !childFound;
}
/**
* expand position path
*
* @param mPath
*/
public void expand(Member[] mPath) {
if (qubonMode) {
resolveUnions();
if (logger.isDebugEnabled()) {
logger.debug("expand after resolveUnions " + this.toString());
}
}
int iDim = mPath.length - 1;
// update the position member tree
// assume mPath = (Product.Drink,Time.2003,Customers.USA)
// 1. find the node N1 for (Product.Drink,Time.2003)
// 2. add the child node Customers.USA.Children to the node N1
//
// if the node N1 for (Product.Drink,Time.2003) was not found:
// we look for a matching node and find for instance
// node N2 = (Product.AllProducts.Children,Time.2003)
// here, we cannot append Customers.USA.Children as a child node.
// we add a new branch
// (Product.Drink,Time.2003,Customers.USA.Children) to the tree.
TreeNode bestNode = findBestNode(mPath);
int bestNodeIndex = bestNode.getLevel() - 1;
// add branch at startNode
// example
// dimensions: Product,MaritalStatus,Gender,Customer
// mPath to Drill Down = (Product.AllProducts, MaritalStatus.M,
// Gender.AllGender)
// MaritalStatus.AllMaritalStatus was drilled down so best match is
// (Product.AllProducts)
// add the branch from MaritalStatus to this node giving
// (Product.AllProducts,MaritalStatus.M,Gender.AllGender.children)
// for the Customer Dimension, add all nodes matching
// (Product.AllProducts, MaritalStatus.M, Gender.AllGender, * )
List tailNodeList;
if (mPath.length < nDimension) {
tailNodeList = collectTailNodes(posTreeRoot, mPath);
} else {
tailNodeList = Collections.EMPTY_LIST;
}
TreeNode newNode;
Object oMember = uti.objForMember(mPath[iDim]);
Object fChildren = uti.createFunCall("Children", new Object[] { oMember},
QuaxUti.FUNTYPE_PROPERTY);
TreeNode parent = bestNode;
// if bestNode is matching mPath[iDim]
// we will add the children Funcall to its parent
// otherwise create path from bestNode to mPath[iDim-1] and
// add the children FunCall there
if (bestNodeIndex == iDim) {
parent = bestNode.getParent();
} else {
for (int i = bestNodeIndex + 1; i < mPath.length - 1; i++) {
oMember = uti.objForMember(mPath[i]);
newNode = new TreeNode(oMember);
parent.addChildNode(newNode);
parent = newNode;
}
}
// any dimension left and including iDim will *not* be excluded from
// hierarchize
int n = nDimension - iDim - 1;
if (n < nHierExclude)
nHierExclude = n;
newNode = new TreeNode(fChildren);
parent.addChildNode(newNode);
if (mPath.length < nDimension) {
for (Iterator iter = tailNodeList.iterator(); iter.hasNext();) {
TreeNode tailNode = (TreeNode) iter.next();
newNode.addChildNode(tailNode.deepCopy());
}
}
if (logger.isDebugEnabled()) {
logger.debug("after expand " + this.toString());
}
qubonMode = false;
hierarchizeNeeded = true;
changed(this, false);
}
/**
* check, whether a member can be expanded
*
* @param monMember
* member to be expanded
*/
public boolean canExpand(Member member) {
// we only allow expand / collapse for a dimension
// left of a "sticky topcount"
if (!allowNavigate(member, false))
return false;
// first check the cache
if (canExpandMemberMap.containsKey(member)) {
Boolean bCanExpand = (Boolean) canExpandMemberMap.get(member);
return bCanExpand.booleanValue();
}
// loop over Position Tree
// reject expansion, if the axis already contains children of member
boolean b = !findMemberChild(member);
// cache the result
Boolean bool = new Boolean(b);
canExpandMemberMap.put(member, bool);
return b;
}
/**
* expand member all over position tree
*
* @param mPath
*/
public void expand(final Member member) {
if (qubonMode) {
resolveUnions();
if (logger.isDebugEnabled()) {
logger.debug("expand after resolveUnions " + this.toString());
}
}
// old stuff, always hierarchize everything
nHierExclude = 0;
final int iDim = this.dimIdx(uti.dimForMember(member));
final List nodesForMember = new ArrayList();
// update the position member tree
// wherever we find monMember, expand it
// collect all nodes for monMember in workList
posTreeRoot.walkChildren(new TreeNodeCallback() {
/**
* callback find node matching member Path exactly
*/
public int handleTreeNode(TreeNode node) {
int iDimNode = node.getLevel() - 1;
if (iDimNode < iDim)
return TreeNodeCallback.CONTINUE; // we are below iDim,
// don't care
// iDimNode == iDim
// node Exp must contain children of member[iDim]
Object oExp = node.getReference();
if (uti.isMember(oExp)) {
if (uti.equalMember(oExp, member))
nodesForMember.add(node);
} else {
// must be FunCall
if (isMemberInFunCall(oExp, member, iDim))
nodesForMember.add(node);
}
return TreeNodeCallback.CONTINUE_SIBLING; // continue next
// sibling
}
});
// add children of member to each node in list
Object oMember = uti.objForMember(member);
Object fChildren = uti.createFunCall("Children", new Object[] { oMember},
QuaxUti.FUNTYPE_PROPERTY);
for (Iterator iter = nodesForMember.iterator(); iter.hasNext();) {
TreeNode node = (TreeNode) iter.next();
TreeNode newNode = new TreeNode(fChildren);
for (Iterator iterator = node.getChildren().iterator(); iterator.hasNext();) {
TreeNode child = (TreeNode) iterator.next();
newNode.addChildNode(child.deepCopy());
}
TreeNode parent = node.getParent();
parent.addChildNode(newNode);
}
if (logger.isDebugEnabled()) {
logger.debug("after expand member " + this.toString());
}
hierarchizeNeeded = true;
changed(this, false);
}
// ==========
// Collapse
// ==========
/**
* check, whether a member path can be collapsed this is true if there is a child position path
*
* @param pathMembers
* position path to be collapsed
*/
public boolean canCollapse(Member[] pathMembers) {
int iDim = pathMembers.length - 1;
// we only allow expand / collapse for a dimension
// left of a "sticky topcount"
if (!allowNavigate(iDim, false))
return false;
// first check the cache
List li = Arrays.asList(pathMembers);
if (canCollapsePosMap.containsKey(li)) {
Boolean bCanCollapse = (Boolean) canCollapsePosMap.get(li);
return bCanCollapse.booleanValue();
}
// loop over Position Tree
// collapse is possible, if the axis already contains child-positions
boolean childFound = checkChildPosition(pathMembers);
// cache the result
Boolean bool = new Boolean(childFound);
canCollapsePosMap.put(li, bool);
return childFound;
}
/**
* remove child positions of mPath from position tree
*
* @param mPath
* member path to be collapsed
*/
public void collapse(final Member[] mPath) {
if (qubonMode) {
resolveUnions();
if (logger.isDebugEnabled()) {
logger.debug("collapse after resolveUnions " + this.toString());
}
}
final int iDim = mPath.length - 1;
// determine FunCall nodes to be split
final List[] splitLists = new List[mPath.length];
for (int i = 0; i < splitLists.length; i++) {
splitLists[i] = new ArrayList();
}
posTreeRoot.walkChildren(new TreeNodeCallback() {
/**
* callback Find child paths of member path. Collect FunCall nodes above in List. We have a
* list for any dimension, so that we can avoid dependency conflicts when we split the
* FunCalls.
*/
public int handleTreeNode(TreeNode node) {
// check, whether this node matches mPath
Object oExp = node.getReference();
int idi = node.getLevel() - 1;
if (idi < iDim) {
if (uti.isMember(oExp)) {
if (uti.equalMember(oExp, mPath[idi]))
return TreeNodeCallback.CONTINUE;
else
return TreeNodeCallback.CONTINUE_SIBLING;
} else {
// Funcall
if (isMemberInFunCall(oExp, mPath[idi], idi))
return TreeNodeCallback.CONTINUE;
else
return TreeNodeCallback.CONTINUE_SIBLING;
}
}
//idi == iDim
// oExp *must* be descendant of mPath[iDim] to get deleted
boolean found = false;
if (uti.isMember(oExp)) {
// Member
if (uti.checkDescendantO(mPath[iDim], oExp)) {
found = true;
}
} else {
// FunCall
if (isChildOfMemberInFunCall(oExp, mPath[iDim], iDim))
found = true;
}
if (found) {
// add this node and all parent nodes, if they are funcalls,
// to split list
int level = node.getLevel();
TreeNode currentNode = node;
while (level > 0) {
Object o = currentNode.getReference();
if (!uti.isMember(o)) {
// Funcall
if (!splitLists[level - 1].contains(currentNode))
splitLists[level - 1].add(currentNode);
}
currentNode = currentNode.getParent();
level = currentNode.getLevel();
}
}
return TreeNodeCallback.CONTINUE_SIBLING;
} // handleTreeNode
});
// split all FunCall nodes collected in worklist
// start with higher levels to avoid dependency conflicts
for (int i = splitLists.length - 1; i >= 0; i--) {
for (Iterator iter = splitLists[i].iterator(); iter.hasNext();) {
TreeNode n = (TreeNode) iter.next();
splitFunCall(n, mPath[i], i);
}
}
// remove child Paths of mPath from position tree
// collect nodes to be deleted
final List removeList = new ArrayList();
posTreeRoot.walkChildren(new TreeNodeCallback() {
/**
* callback remove child nodes of member path, first collect nodes in workList
*/
public int handleTreeNode(TreeNode node) {
// check, whether this node matches mPath
Object oExp = node.getReference();
int idi = node.getLevel() - 1;
if (idi < iDim) {
if (uti.isMember(oExp)) {
if (uti.equalMember(oExp, mPath[idi]))
return TreeNodeCallback.CONTINUE;
else
return TreeNodeCallback.CONTINUE_SIBLING;
} else {
// FunCall
// cannot match as we just did the split of FunCalls
return TreeNodeCallback.CONTINUE_SIBLING;
}
} else if (idi == iDim) {
// *must* be descendant of mPath[iDim] to get deleted
if (!uti.isMember(oExp)) {
// FunCall
if (uti.isFunCallTo(oExp, "Children")) {
Object oMember = uti.funCallArg(oExp, 0);
if (uti.objForMember(mPath[iDim]).equals(oMember)
|| uti.checkDescendantO(mPath[iDim], oMember))
removeList.add(node); // add to delete list
} else if (uti.isFunCallTo(oExp, "{}")) {
// set of members may be there as result of split,
// we will remove any descendant member from the set.
// if the set is empty thereafter, we will add the node
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -