Ejemplo n.º 1
0
  /**
   * recurse through the rule condition elements updating the declaration objecs
   *
   * @param resolver
   * @param contextStack
   * @param element
   */
  private void processElement(
      final DeclarationScopeResolver resolver,
      final Stack contextStack,
      final RuleConditionElement element) {
    if (element instanceof Pattern) {
      Pattern pattern = (Pattern) element;
      for (Iterator it = pattern.getNestedElements().iterator(); it.hasNext(); ) {
        processElement(resolver, contextStack, (RuleConditionElement) it.next());
      }
      for (Constraint next : pattern.getConstraints()) {
        if (next instanceof Declaration) {
          continue;
        }
        Constraint constraint = (Constraint) next;
        Declaration[] decl = constraint.getRequiredDeclarations();
        for (int i = 0; i < decl.length; i++) {
          Declaration resolved = resolver.getDeclaration(null, decl[i].getIdentifier());

          if (constraint instanceof MvelConstraint
              && ((MvelConstraint) constraint).isUnification()) {
            if (ClassObjectType.DroolsQuery_ObjectType.isAssignableFrom(
                resolved.getPattern().getObjectType())) {
              Declaration redeclaredDeclr =
                  new Declaration(
                      resolved.getIdentifier(),
                      ((MvelConstraint) constraint).getFieldExtractor(),
                      pattern,
                      false);
              pattern.addDeclaration(redeclaredDeclr);
            } else {
              ((MvelConstraint) constraint).unsetUnification();
            }
          }

          if (resolved != null && resolved != decl[i] && resolved.getPattern() != pattern) {
            constraint.replaceDeclaration(decl[i], resolved);
          } else if (resolved == null) {
            // it is probably an implicit declaration, so find the corresponding pattern
            Pattern old = decl[i].getPattern();
            Pattern current = resolver.findPatternByIndex(old.getIndex());
            if (current != null && old != current) {
              resolved = new Declaration(decl[i].getIdentifier(), decl[i].getExtractor(), current);
              constraint.replaceDeclaration(decl[i], resolved);
            }
          }
        }
      }
    } else if (element instanceof EvalCondition) {
      Declaration[] decl = ((EvalCondition) element).getRequiredDeclarations();
      for (Declaration aDecl : decl) {
        Declaration resolved = resolver.getDeclaration(null, aDecl.getIdentifier());
        if (resolved != null && resolved != aDecl) {
          ((EvalCondition) element).replaceDeclaration(aDecl, resolved);
        }
      }
    } else if (element instanceof Accumulate) {
      for (RuleConditionElement rce : element.getNestedElements()) {
        processElement(resolver, contextStack, rce);
      }
      ((Accumulate) element).resetInnerDeclarationCache();
    } else if (element instanceof From) {
      DataProvider provider = ((From) element).getDataProvider();
      Declaration[] decl = provider.getRequiredDeclarations();
      for (Declaration aDecl : decl) {
        Declaration resolved = resolver.getDeclaration(null, aDecl.getIdentifier());
        if (resolved != null && resolved != aDecl) {
          provider.replaceDeclaration(aDecl, resolved);
        } else if (resolved == null) {
          // it is probably an implicit declaration, so find the corresponding pattern
          Pattern old = aDecl.getPattern();
          Pattern current = resolver.findPatternByIndex(old.getIndex());
          if (current != null && old != current) {
            resolved = new Declaration(aDecl.getIdentifier(), aDecl.getExtractor(), current);
            provider.replaceDeclaration(aDecl, resolved);
          }
        }
      }
    } else if (element instanceof QueryElement) {
      QueryElement qe = (QueryElement) element;
      Pattern pattern = qe.getResultPattern();

      for (Entry<String, Declaration> entry : pattern.getInnerDeclarations().entrySet()) {
        Declaration resolved = resolver.getDeclaration(null, entry.getValue().getIdentifier());
        if (resolved != null && resolved != entry.getValue() && resolved.getPattern() != pattern) {
          entry.setValue(resolved);
        }
      }

      List<Integer> varIndexes = ArrayUtils.asList(qe.getVariableIndexes());
      for (int i = 0; i < qe.getDeclIndexes().length; i++) {
        Declaration declr = (Declaration) qe.getArgTemplate()[qe.getDeclIndexes()[i]];
        Declaration resolved = resolver.getDeclaration(null, declr.getIdentifier());
        if (resolved != null && resolved != declr && resolved.getPattern() != pattern) {
          qe.getArgTemplate()[qe.getDeclIndexes()[i]] = resolved;
        }

        if (ClassObjectType.DroolsQuery_ObjectType.isAssignableFrom(
            resolved.getPattern().getObjectType())) {
          // if the resolved still points to DroolsQuery, we know this is the first unification
          // pattern, so redeclare it as the visible Declaration
          declr = pattern.addDeclaration(declr.getIdentifier());

          // this bit is different, notice its the ArrayElementReader that we wire up to, not the
          // declaration.
          ArrayElementReader reader =
              new ArrayElementReader(
                  new SelfReferenceClassFieldReader(Object[].class, "this"),
                  qe.getDeclIndexes()[i],
                  resolved.getExtractor().getExtractToClass());

          declr.setReadAccessor(reader);

          varIndexes.add(qe.getDeclIndexes()[i]);
        }
      }
      qe.setVariableIndexes(ArrayUtils.toIntArray(varIndexes));
    } else {
      contextStack.push(element);
      for (RuleConditionElement ruleConditionElement : element.getNestedElements()) {
        processElement(resolver, contextStack, ruleConditionElement);
      }
      contextStack.pop();
    }
  }
Ejemplo n.º 2
0
 public void wire(Object object) {
   setAccumulator((Accumulator) object);
   for (Accumulate clone : this.cloned) {
     clone.wire(object);
   }
 }
Ejemplo n.º 3
0
  public void modifyLeftTuple(
      LeftTuple leftTuple, PropagationContext context, InternalWorkingMemory workingMemory) {
    final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory(this);
    final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject();

    BetaMemory bm = memory.betaMemory;

    // Add and remove to make sure we are in the right bucket and at the end
    // this is needed to fix for indexing and deterministic iteration
    bm.getLeftTupleMemory().removeAdd(leftTuple);

    this.constraints.updateFromTuple(bm.getContext(), workingMemory, leftTuple);
    LeftTuple childLeftTuple = getFirstMatch(leftTuple, accctx, false);

    RightTupleMemory rightMemory = bm.getRightTupleMemory();

    FastIterator rightIt = getRightIterator(rightMemory);

    RightTuple rightTuple = getFirstRightTuple(leftTuple, rightMemory, context, rightIt);

    // first check our index (for indexed nodes only) hasn't changed and we are returning the same
    // bucket
    // if rightTuple is null, we assume there was a bucket change and that bucket is empty
    if (childLeftTuple != null
        && rightMemory.isIndexed()
        && !rightIt.isFullIterator()
        && (rightTuple == null
            || (rightTuple.getMemory() != childLeftTuple.getRightParent().getMemory()))) {
      // our index has changed, so delete all the previous matchings
      removePreviousMatchesForLeftTuple(leftTuple, workingMemory, memory, accctx);

      childLeftTuple = null; // null so the next check will attempt matches for new bucket
    }

    // we can't do anything if RightTupleMemory is empty
    if (rightTuple != null) {
      if (childLeftTuple == null) {
        // either we are indexed and changed buckets or
        // we had no children before, but there is a bucket to potentially match, so try as normal
        // assert
        for (; rightTuple != null; rightTuple = (RightTuple) rightIt.next(rightTuple)) {
          final InternalFactHandle handle = rightTuple.getFactHandle();
          if (this.constraints.isAllowedCachedLeft(bm.getContext(), handle)) {
            // add a new match
            addMatch(leftTuple, rightTuple, null, null, workingMemory, memory, accctx, true);
          }
        }
      } else {
        boolean isDirty = false;
        // in the same bucket, so iterate and compare
        for (; rightTuple != null; rightTuple = (RightTuple) rightIt.next(rightTuple)) {
          final InternalFactHandle handle = rightTuple.getFactHandle();

          if (this.constraints.isAllowedCachedLeft(bm.getContext(), handle)) {
            if (childLeftTuple == null || childLeftTuple.getRightParent() != rightTuple) {
              // add a new match
              addMatch(
                  leftTuple, rightTuple, childLeftTuple, null, workingMemory, memory, accctx, true);
            } else {
              // we must re-add this to ensure deterministic iteration
              LeftTuple temp = childLeftTuple.getLeftParentNext();
              childLeftTuple.reAddRight();
              childLeftTuple = temp;
            }
          } else if (childLeftTuple != null && childLeftTuple.getRightParent() == rightTuple) {
            LeftTuple temp = childLeftTuple.getLeftParentNext();
            // remove the match
            removeMatch(rightTuple, childLeftTuple, workingMemory, memory, accctx, false);
            childLeftTuple = temp;
            // the next line means that when a match is removed from the current leftTuple
            // and the accumulate does not support the reverse operation, then the whole
            // result is dirty (since removeMatch above is not recalculating the total)
            // and we need to do this later
            isDirty = !accumulate.supportsReverse();
          }
          // else do nothing, was false before and false now.
        }
        if (isDirty) {
          reaccumulateForLeftTuple(leftTuple, workingMemory, memory, accctx);
        }
      }
    }

    this.constraints.resetTuple(memory.betaMemory.getContext());
    if (accctx.getAction() == null) {
      evaluateResultConstraints(
          ActivitySource.LEFT, leftTuple, context, workingMemory, memory, accctx, true);
    } // else evaluation is already scheduled, so do nothing
  }