⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 quax.java

📁 OLAP 的客户端代码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
              //  to the remove list.
              int nArgs = uti.funCallArgCount(oExp);
              List removeMembers = new ArrayList();
              for (int i = 0; i < nArgs; i++) {
                Object oSetMember = uti.funCallArg(oExp, i);
                if (uti.checkDescendantO(mPath[iDim], oSetMember)) {
                  removeMembers.add(oSetMember);
                }
              }
              int nRemove = removeMembers.size();
              if (nRemove == nArgs) {
                // all memers in set are descendants, remove the node
                removeList.add(node); // add to delete list
              } else if (nRemove > 0) {
                // remove descendant nodes from set
                Object[] remaining = new Object[nArgs - nRemove];
                int j = 0;
                for (int i = 0; i < nArgs; i++) {
                  Object oSetMember = uti.funCallArg(oExp, i);
                  if (!removeMembers.contains(oSetMember))
                    remaining[j++] = oSetMember;
                }
                if (remaining.length == 1) {
                  node.setReference(remaining[0]); // single
                  // member
                } else {
                  Object newSet = uti.createFunCall("{}", remaining, QuaxUti.FUNTYPE_BRACES);
                  node.setReference(newSet);
                }
              }

            } else if (uti.isFunCallTo(oExp, "Union")) {
              // HHTASK Cleanup, always use removeDescendantsFromFunCall
              Object oRemain = removeDescendantsFromFunCall(oExp, mPath[iDim], iDim);
              if (oRemain == null)
                removeList.add(node);
              else
                node.setReference(oRemain);
            }
            return TreeNodeCallback.CONTINUE_SIBLING;

          } else if (uti.isMember(oExp)) {
            if (uti.checkDescendantO(mPath[iDim], oExp))
              removeList.add(node);
          }
          return TreeNodeCallback.CONTINUE_SIBLING;
          // always break on level iDim, next sibling
        } else {
          // should never get here
          logger.error("unexpected tree node level " + idi + " " + uti.memberString(mPath));
        }
        return TreeNodeCallback.BREAK;
      } // handleTreeNode
    });

    // remove nodes collected in work list
    for (Iterator iter = removeList.iterator(); iter.hasNext();) {
      TreeNode nodeToRemove = (TreeNode) iter.next();
      removePathToNode(nodeToRemove);
    }

    // any dimension left and including iDim will *not* be excluded from
    // hierarchize
    int n = nDimension - iDim - 1;
    if (n < nHierExclude)
      nHierExclude = n;

    if (logger.isDebugEnabled()) {
      logger.debug("after collapse " + this.toString());
    }

    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 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 (canCollapseMemberMap.containsKey(member)) {
      Boolean bCanCollapse = (Boolean) canCollapseMemberMap.get(member);
      return bCanCollapse.booleanValue();
    }

    // loop over Position Tree
    //  can collapse, if we find a descendant of monMember
    boolean b = findMemberChild(member);

    // cache the result
    Boolean bool = new Boolean(b);
    canCollapseMemberMap.put(member, bool);

    return b;
  }

  /**
   * remove child nodes of monMember
   * 
   * @param monMember
   *          member to be collapsed
   */
  public void collapse(final Member member) {

    if (qubonMode) {
      resolveUnions();
      if (logger.isDebugEnabled()) {
        logger.debug("collapse member after resolveUnions " + this.toString());
      }
    }

    final int iDim = this.dimIdx(uti.dimForMember(member));

    final List nodesForMember = new ArrayList();

    // update the position member tree
    //  wherever we find a descendant node of monMember, split and remove it
    //  collect all descendant 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.checkDescendantO(member, oExp))
            nodesForMember.add(node);
        } else {
          // must be FunCall

          if (isDescendantOfMemberInFunCall(oExp, member, iDimNode))
            nodesForMember.add(node);
        }
        return TreeNodeCallback.CONTINUE_SIBLING; // continue next
        // sibling
      }
    });

    for (Iterator iter = nodesForMember.iterator(); iter.hasNext();) {
      TreeNode node = (TreeNode) iter.next();
      Object oExp = node.getReference();
      if (uti.isMember(oExp)) {
        removePathToNode(node);
      } else {
        // FunCall
        Object oComplement = removeDescendantsFromFunCall(oExp, member, iDim);
        if (oComplement == null)
          removePathToNode(node);
        else
          node.setReference(oComplement); // replace node object by complement
      }
    }
    if (logger.isDebugEnabled()) {
      logger.debug("after collapse " + this.toString());
    }

    changed(this, false);
  } // collapse

  // ==========
  // Drill Down
  // ==========

  /**
   * drill down is possible if there is no sticky generate
   */
  public boolean canDrillDown(Member member) {
    return allowNavigate(member, true);
  }

  /**
   * drill down
   * 
   * @param monMember
   *          drill down member
   */
  public void drillDown(Member member) {
    final int iDim = this.dimIdx(uti.dimForMember(member));

    // collect the Exp's of all dimensions except iDim
    Object[] sets = new Object[nDimension];
    Object oMember = uti.objForMember(member);
    Object fChildren = uti.createFunCall("Children", new Object[] { oMember},
        QuaxUti.FUNTYPE_PROPERTY);
    DimensionLoop: for (int i = 0; i < nDimension; i++) {
      if (i == iDim) {
        // replace drilldown dimension by member.children
        sets[i] = fChildren;
      } else {
        // generate exp for all nodes of this dimension
        sets[i] = genExpForDim(i);
      }
    } // DimensionLoop

    // regenerate the position tree as crossjoin of sets
    regeneratePosTree(sets, false);

    changed(this, false);
  }

  // ==========
  // Drill Up
  // ==========

  /**
   * drill up is possible if at least one member in the tree is not at the top level of this
   * hierarchy.
   */
  public boolean canDrillUp(Hierarchy hier) {
    final int iDim = this.dimIdx(hier.getDimension());

    if (!allowNavigate(iDim, true))
      return false;

    int ret = posTreeRoot.walkChildren(new TreeNodeCallback() {

      /**
       * callback check for member of hierarchy not on top level
       */
      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
          if (isFunCallNotTopLevel(oExp, iDimNode))
            return TreeNodeCallback.BREAK; // got it
          else
            return TreeNodeCallback.CONTINUE_SIBLING;
        } else {
          // member

          if (uti.levelDepthForMember(oExp) > 0)
            return TreeNodeCallback.BREAK; // got it
          else
            return TreeNodeCallback.CONTINUE_SIBLING;
        } // member

      } // handlePositionTreeNode
    });

    return (ret == TreeNodeCallback.BREAK);
  }

  /**
   * drill down
   * 
   * @param monMember
   *          drill down member
   */
  public void drillUp(Hierarchy hier) {

    int iDim = dimIdx(hier.getDimension());

    // collect the Exp's of all dimensions
    Object[] sets = new Object[nDimension];

    DimensionLoop: for (int i = 0; i < nDimension; i++) {
      if (i == iDim) {
        // replace drillup dimension by drillup set
        sets[i] = drillupExp(iDim, hier);
      } else {
        sets[i] = genExpForDim(i);
      }
    } // DimensionLoop

    // regenerate the position tree as crossjoin of sets
    regeneratePosTree(sets, false);

    changed(this, false);
  }

  // ==========
  // Query Axis Set
  // ==========

  /**
   * MDX Generation
   * generate Exp from tree
   * 
   * @return Exp for axis set
   */
  public Object genExp(boolean genHierarchize) {

    if (generateMode > 0 && generateIndex > 0)
      return genGenerateExp(genHierarchize);
    else
      return genNormalExp(genHierarchize);
  }

  /**
   * Normal MDX Generation - no Generate
   * 
   * @return Exp for axis set
   */
  private Object genNormalExp(boolean genHierarchize) {

    ExpGenerator expGenerator = new ExpGenerator(uti);

    if (!genHierarchize) {
      // no Hierarchize
      expGenerator.init(posTreeRoot, hiers);
      Object exp = expGenerator.genExp();
      return exp;
    }

    // do we need a special hierarchize ?
    // this will be true, if nHierExclude > 0

    if (nHierExclude == 0) {
      // no special hierarchize needed
      expGenerator.init(posTreeRoot, hiers);
      Object exp = expGenerator.genExp();
      // Hierarchize around "everything"
      Object eHier = uti
          .createFunCall("Hierarchize", new Object[] { exp}, QuaxUti.FUNTYPE_FUNCTION);
      return eHier;
    }

    // special hierarchize to be generated
    // the Qubon Mode Hierarchies are factored out,
    //  as they consist only of a single set of members.
    // the left expression will be generated and then hierarchized,
    //  *before* beeing crossjoined to the right Expression.

    return genLeftRight(expGenerator, nDimension - nHierExclude, nHierExclude);
  }

  /**
   * generate an expression 
   * with hierarchize for the hierarchies < nHierExclude 
   * without hierarchize for the hierarchies >= nHierExclude
   */
  private Object genLeftRight(ExpGenerator expGenerator, int nLeft, int nRight) {
    // generate left expression to be hierarchized
    Object leftExp = null;
    if (nLeft > 0) {
      TreeNode leftRoot = posTreeRoot.deepCopyPrune(nLeft);
      leftRoot.setReference(null);
      Hierarchy[] leftHiers = new Hierarchy[nLeft];
      for (int i = 0; i < leftHiers.length; i++) {
        leftHiers[i] = hiers[i];
      }
      expGenerator.init(leftRoot, leftHiers);
      leftExp = expGenerator.genExp();
      leftExp = uti.createFunCall("Hierarchize", new Object[] { leftExp}, QuaxUti.FUNTYPE_FUNCTION);
    }

    // generate the right expression, not to be hierarchized
    Object rightExp = null;
    Hierarchy[] rightHiers = new Hierarchy[nRight];
    for (int i = 0; i < nRight; i++) {
      rightHiers[i] = hiers[nLeft + i];
    }
    
    // go down to the first hier to be excluded from hierarchize
    // note: the subtree tree under any node of the hierarchy above
    //  is always the same, so we can replicate any subtree under
    //  a node of hierarchy nLeft-1
    TreeNode rightRoot = new TreeNode(null);
    TreeNode current = posTreeRoot;
    for (int i = 0; i < nLeft; i++) {
      List list = current.getChildren();
      current = (TreeNode) list.get(0);
    }
    List list = current.getChildren();
    for (Iterator iter = list.iterator(); iter.hasNext();) {
      TreeNode node = (TreeNode) iter.next();
      TreeNode cnode = node.deepCopy();
      rightRoot.addChildNode(cnode);
    }

    expGenerator.init(rightRoot, rightHiers);
    rightExp = expGenerator.genExp();

    if (leftExp == null)
      return rightExp;

    Object exp = uti.createFunCall("CrossJoin", new Object[] { leftExp, rightExp},
        QuaxUti.FUNTYPE_FUNCTION);

    return exp;
  }

  /**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -