コード例 #1
0
ファイル: LastNonEmptyUdf.java プロジェクト: inevo/mondrian
 public Object execute(Evaluator evaluator, Argument[] arguments) {
   final Argument memberListExp = arguments[0];
   final List memberList = (List) memberListExp.evaluate(evaluator);
   final Argument exp = arguments[1];
   int nullCount = 0;
   int missCount = 0;
   for (int i = memberList.size() - 1; i >= 0; --i) {
     Member member = (Member) memberList.get(i);
     // Create an evaluator with the member as its context.
     Evaluator subEvaluator = evaluator.push(member);
     int missCountBefore = subEvaluator.getMissCount();
     final Object o = exp.evaluateScalar(subEvaluator);
     int missCountAfter = subEvaluator.getMissCount();
     if (Util.isNull(o)) {
       ++nullCount;
       continue;
     }
     if (missCountAfter > missCountBefore) {
       // There was a cache miss while evaluating the expression, so
       // the result is bogus. It would be a mistake to give up after
       // one cache miss, because then it would take us N
       // evaluate/fetch passes to move back through N members, which
       // is way too many.
       //
       // Carry on until we have seen as many misses as we have seen
       // null cells. The effect of this policy is that each pass
       // examines twice as many cells as the previous pass. Thus
       // we can move back through N members in log2(N) passes.
       ++missCount;
       if (missCount < 2 * nullCount + 1) {
         continue;
       }
     }
     if (o == RolapUtil.valueNotReadyException) {
       // Value is not in the cache yet, so we don't know whether
       // it will be empty. Carry on...
       continue;
     }
     if (o instanceof RuntimeException) {
       RuntimeException runtimeException = (RuntimeException) o;
       if (o == RolapUtil.valueNotReadyException) {
         // Value is not in the cache yet, so we don't know whether
         // it will be empty. Carry on...
         continue;
       }
       return runtimeException;
     }
     return member;
   }
   // Not found. Return the hierarchy's 'null member'.
   // It is possible that a MemberType has a Dimension but
   // no hierarchy, so we have to just get the type's Dimension's
   // default hierarchy and return it's null member.
   final Hierarchy hierarchy = memberListExp.getType().getHierarchy();
   return (hierarchy == null)
       ? memberListExp.getType().getDimension().getHierarchies()[0].getNullMember()
       : hierarchy.getNullMember();
 }
コード例 #2
0
ファイル: TupleValueCalc.java プロジェクト: inevo/mondrian
  public Object evaluate(Evaluator evaluator) {
    final Member[] members = tupleCalc.evaluateTuple(evaluator);
    if (members == null) {
      return null;
    }

    final boolean needToReturnNull = evaluator.needToReturnNullForUnrelatedDimension(members);
    if (needToReturnNull) {
      return null;
    }

    Member[] savedMembers = new Member[members.length];
    for (int i = 0; i < members.length; i++) {
      savedMembers[i] = evaluator.setContext(members[i]);
    }
    Object result = evaluator.evaluateCurrent();
    evaluator.setContext(savedMembers);
    return result;
  }
コード例 #3
0
ファイル: ScenarioImpl.java プロジェクト: rikima/mondrian
    public Object evaluate(Evaluator evaluator) {
      // Evaluate current member in the given scenario by expanding in
      // terms of the writeback cells.

      // First, evaluate in the null scenario.
      final Member defaultMember = scenario.member.getHierarchy().getDefaultMember();
      final int savepoint = evaluator.savepoint();
      try {
        evaluator.setContext(defaultMember);
        final Object o = evaluator.evaluateCurrent();
        double d = o instanceof Number ? ((Number) o).doubleValue() : 0d;

        // Look for writeback cells which are equal to, ancestors of,
        // or descendants of, the current cell. Modify the value
        // accordingly.
        //
        // It is possible that the value is modified by several
        // writebacks. If so, order is important.
        int changeCount = 0;
        for (ScenarioImpl.WritebackCell writebackCell : scenario.writebackCells) {
          CellRelation relation = writebackCell.getRelationTo(evaluator.getMembers());
          switch (relation) {
            case ABOVE:
              // This cell is below the writeback cell. Value is
              // determined by allocation policy.
              double atomicCellCount = evaluateAtomicCellCount((RolapEvaluator) evaluator);
              if (atomicCellCount == 0d) {
                // Sometimes the value comes back zero if the cache
                // is not ready. Switch to 1, which at least does
                // not give divide-by-zero. We will be invoked again
                // for the correct answer when the cache has been
                // populated.
                atomicCellCount = 1d;
              }
              switch (writebackCell.allocationPolicy) {
                case EQUAL_ALLOCATION:
                  d = writebackCell.newValue * atomicCellCount / writebackCell.atomicCellCount;
                  break;
                case EQUAL_INCREMENT:
                  d += writebackCell.getOffset() * atomicCellCount / writebackCell.atomicCellCount;
                  break;
                default:
                  throw Util.unexpected(writebackCell.allocationPolicy);
              }
              ++changeCount;
              break;
            case EQUAL:
              // This cell is the writeback cell. Value is the value
              // written back.
              d = writebackCell.newValue;
              ++changeCount;
              break;
            case BELOW:
              // This cell is above the writeback cell. Value is the
              // current value plus the change in the writeback cell.
              d += writebackCell.getOffset();
              ++changeCount;
              break;
            case NONE:
              // Writeback cell is unrelated. It has no effect on
              // cell's value.
              break;
            default:
              throw Util.unexpected(relation);
          }
        }
        // Don't create a new object if value has not changed.
        if (changeCount == 0) {
          return o;
        } else {
          return d;
        }
      } finally {
        evaluator.restore(savepoint);
      }
    }