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

📄 quax.java

📁 OLAP 的客户端代码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
   * MDX Generation for Generate
   * 
   * @return Exp for axis set
   */
  private Object genGenerateExp(boolean genHierarchize) {

    ExpGenerator expGenerator = new ExpGenerator(uti);

    // Generate(GSet, FSet) to be generated
    //  hierarchies >= generateIndex will not be "hierarchized"
    // we expect the hierarchies >= generateIndex to be excluded
    //  from hierarchize. 
    if (nDimension - generateIndex > nHierExclude)
      logger.warn("unexpected values: nHierExclude=" + nHierExclude + " generateIndex="
          + generateIndex);

    // assume following situation:
    //  3 hierarchies
    // time - customers - product
    // we want top 5 customers, generated for each time member
    // 1. step
    //  generate expression until customers (only time here), result = set1
    //  if neccessary, put hierarchize around
    // 2. step
    //  Generate(set1, Topcount(Crossjoin ({Time.Currentmember}, Set for Customers),
    //                          5, condition))
    //  result = set2
    // 3.step
    //  append the tail nodes , here Product
    //  Crossjoin(set2 , Product dimension nodes)
    // 
    // 1. step left expression, potentially hierarchized

    Object leftExp = null;
    // if     nHierExclude > nDimension - generateIndex
    //    and nHierExclude < nDimension
    // the the left expression (inside Generate) will be partly
    // hierarchized
    if (genHierarchize && nHierExclude > nDimension - generateIndex && nHierExclude < nDimension) {
      int nLeft = nDimension - nHierExclude;
      int nRight = generateIndex - nLeft;
      leftExp = genLeftRight(expGenerator, nLeft, nRight);
    } else {
      TreeNode leftRoot = posTreeRoot.deepCopyPrune(generateIndex);
      leftRoot.setReference(null);
      Hierarchy[] leftHiers = new Hierarchy[generateIndex];
      for (int i = 0; i < leftHiers.length; i++) {
        leftHiers[i] = hiers[i];
      }
      expGenerator.init(leftRoot, leftHiers);
      leftExp = expGenerator.genExp();
      if (genHierarchize)
        leftExp = uti.createFunCall("Hierarchize", new Object[] { leftExp},
            QuaxUti.FUNTYPE_FUNCTION);
    }

    // 2. step Generate(set1, Topcount())
    TreeNode topCountNode = posTreeRoot;
    // top count node can be anything like topcount, bottomcount, filter
    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();
    // we have to replace the "set" of the topcount function
    Object origTopcountSet = uti.funCallArg(topcount, 0);
    // generate the Tuple of dimension.currentmember until generateIndex
    Object currentMembersTuple = genCurrentTuple();
    Object ocj = uti.createFunCall("Crossjoin",
        new Object[] { currentMembersTuple, origTopcountSet}, QuaxUti.FUNTYPE_FUNCTION);
    // replace the topcout original set
    String fun = uti.funCallName(topcount);
    int n = uti.funCallArgCount(topcount);
    Object[] args = new Object[n];
    for (int i = 1; i < n; i++) {
      args[i] = uti.funCallArg(topcount, i);
    }
    args[0] = ocj;
    Object newTopcount = uti.createFunCall(fun, args, QuaxUti.FUNTYPE_FUNCTION);
    Object oGenerate = uti.createFunCall("Generate", new Object[] { leftExp, newTopcount},
        QuaxUti.FUNTYPE_FUNCTION);

    if (generateIndex + 1 == nDimension)
      return oGenerate;

    // 3. step append the tail nodes
    // generate CrossJoin
    int nRight = nDimension - generateIndex - 1;
    Hierarchy[] rightHiers = new Hierarchy[nRight];
    for (int i = 1; i <= nRight; i++) {
      rightHiers[nRight - i] = hiers[nDimension - i];
    }
    TreeNode root = new TreeNode(null);
    List list = topCountNode.getChildren();
    for (Iterator iter = list.iterator(); iter.hasNext();) {
      TreeNode node = (TreeNode) iter.next();
      root.addChildNode(node.deepCopy());
    }
    expGenerator.init(root, rightHiers);
    Object rightExp = expGenerator.genExp();

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

  // ==========
  // private
  // ==========

  /**
   * generate {(dim1.Currentmember, dim2.Currentmember, ... )}
   * 
   * @return
   */
  private Object genCurrentTuple() {
    Object[] currentsOfDim = new Object[generateIndex];
    for (int i = 0; i < currentsOfDim.length; i++) {
      Dimension dim = hiers[i].getDimension();
      currentsOfDim[i] = uti.createFunCall("CurrentMember", new Object[] { uti.objForDim(dim)},
          QuaxUti.FUNTYPE_PROPERTY);
    }
    Object oTuple;
    if (generateIndex > 1)
      oTuple = uti.createFunCall("()", currentsOfDim, QuaxUti.FUNTYPE_TUPLE);
    else
      oTuple = currentsOfDim[0]; //  just dimension.currentmember
    // generate set braces around tuple
    Object oSet = uti.createFunCall("{}", new Object[] { oTuple}, QuaxUti.FUNTYPE_BRACES);
    return oSet;
  }

  /**
   * @return true if child position can be found
   */
  private boolean checkChildPosition(final Member[] mPath) {

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

      /**
       * callback find node matching member Path exactly
       */
      public int handleTreeNode(TreeNode node) {
        int iDim = mPath.length - 1;
        int iDimNode = node.getLevel() - 1;
        Object oExp = node.getReference();
        if (iDimNode < iDim) {
          // node Exp must match member[iDim]
          if (uti.isMember(oExp)) {
            if (uti.equalMember(oExp, mPath[iDimNode]))
              return TreeNodeCallback.CONTINUE;
            else
              return TreeNodeCallback.CONTINUE_SIBLING; // continue
            // next
            // sibling
          } else {
            // must be FunCall
            if (isMemberInFunCall(oExp, mPath[iDimNode], iDimNode))
              return TreeNodeCallback.CONTINUE;
            else
              return TreeNodeCallback.CONTINUE_SIBLING; // continue
            // next
            // sibling
          }
        }

        // iDimNode == iDim
        //  node Exp must contain children of member[iDim]
        if (uti.isMember(oExp)) {
          if (uti.checkParent(mPath[iDimNode], oExp))
            return TreeNodeCallback.BREAK; // found
          else
            return TreeNodeCallback.CONTINUE_SIBLING; // continue
          // next
          // sibling
        } else {
          // must be FunCall
          if (isChildOfMemberInFunCall(oExp, mPath[iDimNode], iDimNode))
            return TreeNodeCallback.BREAK; // found
          else
            return TreeNodeCallback.CONTINUE_SIBLING; // continue
          // next
          // sibling
        }
      }
    });

    if (ret == TreeNodeCallback.BREAK)
      return true; // child path fund
    else
      return false;
  } // checkChildPosition

  /**
   * resolve the qubon mode unions and crossjoins only used in "old" expand mode
   */
  private void resolveUnions() {
    final List[] setLists = new List[nDimension];
    for (int i = 0; i < setLists.length; i++) {
      setLists[i] = new ArrayList();
    }
    posTreeRoot.walkChildren(new TreeNodeCallback() {

      /**
       * callback resolve sets of any dimension
       */
      public int handleTreeNode(TreeNode node) {
        int iDimNode = node.getLevel() - 1;
        Object oExp = node.getReference();
        if (!uti.isMember(oExp)) {
          // FunCall
          funToList(oExp, setLists[iDimNode]);
        } else {
          // member
          setLists[iDimNode].add(oExp);
        }
        return TreeNodeCallback.CONTINUE;
      } // handleTreeNode
    });

    // unions and sets are resolved, now resolve crossjoins
    posTreeRoot = new TreeNode(null);
    crossJoinTree(setLists, posTreeRoot, 0);

    qubonMode = false;
  }

  /**
   * find best tree node for member path (longest match)
   */
  private TreeNode findBestNode(final Member[] mPath) {
    final TreeNode[] bestNode = new TreeNode[1];
    bestNode[0] = posTreeRoot;
    posTreeRoot.walkChildren(new TreeNodeCallback() {

      /**
       * callback find node matching member Path exactly
       */
      public int handleTreeNode(TreeNode node) {
        int iDim = mPath.length - 1;
        int iDimNode = node.getLevel() - 1;
        Object oExp = node.getReference();
        if (!uti.isMember(oExp))
          return TreeNodeCallback.CONTINUE_SIBLING; // continue next
        // sibling
        if (uti.equalMember(oExp, mPath[iDimNode])) {
          // match
          if (iDimNode == iDim) {
            // found exactly matching node
            bestNode[0] = node;
            return TreeNodeCallback.BREAK;
          } else {
            // best match up to now
            bestNode[0] = node;
            return TreeNodeCallback.CONTINUE;
          }
        } else {
          // no match
          return TreeNodeCallback.CONTINUE_SIBLING; // continue next
          // sibling
        }
      }
    });

    return bestNode[0];
  }

  /**
   * collect tail nodes for all nodes matching member path
   */
  private List collectTailNodes(TreeNode startNode, final Member[] mPath) {

    final List tailNodes = new ArrayList();
    startNode.walkChildren(new TreeNodeCallback() {

      /**
       * callback find node matching mPath collect tail nodes
       */
      public int handleTreeNode(TreeNode node) {
        int iDim = mPath.length - 1;
        int iDimNode = node.getLevel() - 1;
        Object oExp = node.getReference();
        boolean match = false;
        if (uti.isMember(oExp)) {
          // exp is member
          if (uti.equalMember(oExp, mPath[iDimNode]))
            match = true;
        } else {
          // must be FunCall
          if (isMemberInFunCall(oExp, mPath[iDimNode], iDimNode))
            match = true;
        }

        if (match) {
          if (iDimNode == iDim) {
            // add the children to the tail list
            tailNodes.addAll(node.getChildren());
            return TreeNodeCallback.CONTINUE_SIBLING;
          } else {
            // iDimNode < iDim
            return TreeNodeCallback.CONTINUE;
          }
        } else
          return TreeNodeCallback.CONTINUE_SIBLING; // no match,
        // continue next
        // sibling

      } // handlePositionTreeNode
    });

    return tailNodes;
  }

  private boolean findMemberChild(final Member member) {

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

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

      /**
       * callback find child node of monMember
       */
      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.checkParent(member, oExp))
            return TreeNodeCallback.BREAK; // found
        } else {
          // must be FunCall
          if (isChildOfMemberInFunCall(oExp, member, iDimNode))
            return TreeNodeCallback.BREAK; // found
        }
        return TreeNodeCallback.CONTINUE_SIBLING; // continue next
        // sibling
      }
    });

    return (ret == TreeNodeCallback.BREAK);
  }

  /**
   * String representation (debugging)
   */
  public String toString() {
    final StringBuffer sbPosTree = new StringBuffer();
    sbPosTree.append("number of hierarchies excluded from HIEARARCHIZE=" + nHierExclude);
    sbPosTree.append('\n');
    if (posTreeRoot == null) {
      sbPosTree.append("Root=null");
      return sbPosTree.toString();
    }
    posTreeRoot.walkChildren(new TreeNodeCallback() {

      /**
       * callback quax to String
       */
      public int handleTreeNode(TreeNode node) {
        int iDimNode = node.getLevel() - 1;
        sbPosTree.append("\n");
        for (int i = 0; i < iDimNode - 1; i++) {
          sbPosTree.append("   ");
        }
        if (iDimNode > 0) {
          sbPosTree.append("+--");
        }

        Object oExp = node.getReference();
        if (!uti.isMember(oExp)) {
          // FunCall
          sbPosTree.append(uti.funString(oExp));
        } else {
          // member
          sbPosTree.append(uti.getMemberUniqueName(oExp));
        }
        return TreeNodeCallback.CONTINUE;
      } // handleTreeNode
    });
    return sbPosTree.toString();
  }

  /**
   * build tree resolving crossjoin
   * 
   * @param currentNode
   * @param iDim
   */
  private void crossJoinTree(List[] setLists, TreeNode currentNode, int iDim) {
    for (Iterator iter = setLists[iDim].iterator(); iter.hasNext();) {
      Object oExp = iter.next();
      TreeNode newNode = new TreeNode(oExp);
      if (iDim < nDimension - 1)
        crossJoinTree(setLists, newNode, iDim + 1);
      currentNode.addChildNode(newNode);
    }
  }

⌨️ 快捷键说明

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