public void testLiteralConstraintAssertSequentialMode() throws Exception {
    RuleBaseConfiguration config = new RuleBaseConfiguration();
    config.setSequential(true);
    ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(config);
    BuildContext buildContext =
        new BuildContext(ruleBase, ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator());
    ReteooWorkingMemory workingMemory = new ReteooWorkingMemory(buildContext.getNextId(), ruleBase);

    final Rule rule = new Rule("test-rule");
    final PropagationContext context =
        new PropagationContextImpl(0, PropagationContext.ASSERTION, null, null);

    final MockObjectSource source = new MockObjectSource(buildContext.getNextId());

    final ClassFieldExtractor extractor =
        cache.getExtractor(Cheese.class, "type", getClass().getClassLoader());

    final FieldValue field = FieldFactory.getFieldValue("cheddar");

    final Evaluator evaluator = ValueType.OBJECT_TYPE.getEvaluator(Operator.EQUAL);

    final LiteralConstraint constraint = new LiteralConstraint(extractor, evaluator, field);

    // With Memory
    final AlphaNode alphaNode =
        new AlphaNode(buildContext.getNextId(), constraint, source, buildContext); // has memory

    final MockObjectSink sink = new MockObjectSink();
    alphaNode.addObjectSink(sink);

    final Cheese cheddar = new Cheese("cheddar", 5);
    final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert(cheddar);

    // check sink is empty
    assertLength(0, sink.getAsserted());

    // check alpha memory is empty
    final AlphaMemory memory = (AlphaMemory) workingMemory.getNodeMemory(alphaNode);

    assertNull(memory.facts);

    // object should assert as it passes text
    alphaNode.assertObject(f0, context, workingMemory);

    assertEquals(1, sink.getAsserted().size());
    assertNull(memory.facts);
    Object[] list = (Object[]) sink.getAsserted().get(0);
    assertSame(cheddar, workingMemory.getObject((DefaultFactHandle) list[0]));

    final Cheese stilton = new Cheese("stilton", 6);
    final DefaultFactHandle f1 = new DefaultFactHandle(1, stilton);

    // object should NOT assert as it does not pass test
    alphaNode.assertObject(f1, context, workingMemory);

    assertLength(1, sink.getAsserted());
    assertNull(memory.facts);
    list = (Object[]) sink.getAsserted().get(0);
    assertSame(cheddar, workingMemory.getObject((DefaultFactHandle) list[0]));
  }
  public void testRetractObjectWithMemory() throws Exception {
    RuleBaseConfiguration config = new RuleBaseConfiguration();
    config.setAlphaMemory(true);
    ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(config);
    BuildContext buildContext =
        new BuildContext(ruleBase, ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator());
    ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();

    final Rule rule = new Rule("test-rule");
    final PropagationContext context =
        new PropagationContextImpl(0, PropagationContext.ASSERTION, null, null);

    final MockObjectSource source = new MockObjectSource(buildContext.getNextId());

    final FieldExtractor extractor =
        cache.getExtractor(Cheese.class, "type", getClass().getClassLoader());

    final FieldValue field = FieldFactory.getFieldValue("cheddar");

    final Evaluator evaluator = ValueType.OBJECT_TYPE.getEvaluator(Operator.EQUAL);

    final LiteralConstraint constraint = new LiteralConstraint(extractor, evaluator, field);

    buildContext.setAlphaNodeMemoryAllowed(true);
    final AlphaNode alphaNode =
        new AlphaNode(buildContext.getNextId(), constraint, source, buildContext); // has memory
    final MockObjectSink sink = new MockObjectSink();
    alphaNode.addObjectSink(sink);

    final Cheese cheddar = new Cheese("cheddar", 5);

    final DefaultFactHandle f0 = new DefaultFactHandle(0, cheddar);

    // check alpha memory is empty
    final AlphaMemory memory = (AlphaMemory) workingMemory.getNodeMemory(alphaNode);
    assertEquals(0, memory.facts.size());

    // object should assert as it passes text
    alphaNode.assertObject(f0, context, workingMemory);

    assertEquals(1, memory.facts.size());

    final DefaultFactHandle f1 = new DefaultFactHandle(1, "cheese");

    // object should NOT retract as it doesn't exist
    alphaNode.retractObject(f1, context, workingMemory);

    assertLength(0, sink.getRetracted());
    assertEquals(1, memory.facts.size());
    assertTrue("Should contain 'cheddar handle'", memory.facts.contains(f0));

    // object should retract as it does exist
    alphaNode.retractObject(f0, context, workingMemory);

    assertLength(1, sink.getRetracted());
    assertEquals(0, memory.facts.size());
    final Object[] list = (Object[]) sink.getRetracted().get(0);
    assertSame(f0, list[0]);
  }
 /**
  * Constructor specifying the unique id of the node in the Rete network, the position of the propagating <code>FactHandleImpl</code> in
  * <code>ReteTuple</code> and the source that propagates the receive <code>ReteTuple<code>s.
  *
  * @param id
  *      Unique id
  * @param source
  *      The <code>TupleSource</code> which propagates the received <code>ReteTuple</code>
  */
 public RightInputAdapterNode(
     final int id, final LeftTupleSource source, final BuildContext context) {
   super(
       id,
       context.getPartitionId(),
       context.getRuleBase().getConfiguration().isMultithreadEvaluation());
   this.tupleSource = source;
   this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
 }
Exemple #4
0
  @Test
  public void testLiteralConstraintAssertObjectWithoutMemory() throws Exception {
    ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
    BuildContext buildContext =
        new BuildContext(ruleBase, ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator());
    ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();

    final Rule rule = new Rule("test-rule");
    final PropagationContext context =
        new PropagationContextImpl(0, PropagationContext.INSERTION, null, null, null);

    final MockObjectSource source = new MockObjectSource(buildContext.getNextId());

    final ClassFieldReader extractor =
        store.getReader(Cheese.class, "type", getClass().getClassLoader());

    final FieldValue field = FieldFactory.getInstance().getFieldValue("cheddar");

    final MvelConstraint constraint =
        new MvelConstraintTestUtil("type == \"cheddar\"", field, extractor);

    // With Memory
    final AlphaNode alphaNode =
        new AlphaNode(buildContext.getNextId(), constraint, source, buildContext); // no memory

    final MockObjectSink sink = new MockObjectSink();
    alphaNode.addObjectSink(sink);

    final Cheese cheddar = new Cheese("cheddar", 5);
    final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert(cheddar);

    // check sink is empty
    assertLength(0, sink.getAsserted());

    // check alpha memory is empty
    final AlphaMemory memory = (AlphaMemory) workingMemory.getNodeMemory(alphaNode);

    // object should assert as it passes text
    alphaNode.assertObject(f0, context, workingMemory);

    assertEquals(1, sink.getAsserted().size());

    Object[] list = (Object[]) sink.getAsserted().get(0);
    assertSame(cheddar, workingMemory.getObject((DefaultFactHandle) list[0]));

    final Cheese stilton = new Cheese("stilton", 6);
    final DefaultFactHandle f1 = new DefaultFactHandle(1, stilton);

    // object should NOT assert as it does not pass test
    alphaNode.assertObject(f1, context, workingMemory);

    assertLength(1, sink.getAsserted());

    list = (Object[]) sink.getAsserted().get(0);
    assertSame(cheddar, workingMemory.getObject((DefaultFactHandle) list[0]));
  }
Exemple #5
0
 public EntryPointNode(final int id, final ObjectSource objectSource, final BuildContext context) {
   this(
       id,
       context.getPartitionId(),
       context.getRuleBase().getConfiguration().isMultithreadEvaluation(),
       objectSource,
       context
           .getCurrentEntryPoint()); // irrelevant for this node, since it overrides sink
                                     // management
 }
  /*
   * dont need to test with and without memory on this, as it was already done
   * on the previous two tests. This just test AlphaNode With a different
   * Constraint type.
   */
  public void testReturnValueConstraintAssertObject() throws Exception {
    RuleBaseConfiguration config = new RuleBaseConfiguration();
    config.setAlphaMemory(false);
    ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(config);
    BuildContext buildContext =
        new BuildContext(ruleBase, ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator());
    ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();

    final Rule rule = new Rule("test-rule");
    final PropagationContext context =
        new PropagationContextImpl(0, PropagationContext.ASSERTION, null, null);

    final MockObjectSource source = new MockObjectSource(buildContext.getNextId());

    final FieldExtractor extractor =
        cache.getExtractor(Cheese.class, "type", getClass().getClassLoader());

    final FieldValue field = FieldFactory.getFieldValue("cheddar");

    final Evaluator evaluator = ValueType.OBJECT_TYPE.getEvaluator(Operator.EQUAL);

    final LiteralConstraint constraint = new LiteralConstraint(extractor, evaluator, field);

    final AlphaNode alphaNode =
        new AlphaNode(buildContext.getNextId(), constraint, source, buildContext);
    final MockObjectSink sink = new MockObjectSink();
    alphaNode.addObjectSink(sink);

    final Cheese cheddar = new Cheese("cheddar", 5);

    final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert(cheddar);

    assertLength(0, sink.getAsserted());

    // object should assert as it passes text
    alphaNode.assertObject(f0, context, workingMemory);

    assertLength(1, sink.getAsserted());
    final Object[] list = (Object[]) sink.getAsserted().get(0);
    assertSame(cheddar, workingMemory.getObject((DefaultFactHandle) list[0]));

    final Cheese stilton = new Cheese("stilton", 6);
    f0.setObject(stilton);

    sink.getAsserted().clear();

    // object should not assert as it does not pass text
    alphaNode.assertObject(f0, context, workingMemory);

    assertLength(0, sink.getAsserted());
  }
 /**
  * Constructus a LeftInputAdapterNode with a unique id that receives <code>FactHandle</code> from
  * a parent <code>ObjectSource</code> and adds it to a given pattern in the resulting Tuples.
  *
  * @param id The unique id of this node in the current Rete network
  * @param source The parent node, where Facts are propagated from
  */
 public LeftInputAdapterNode(final int id, final ObjectSource source, final BuildContext context) {
   super(
       id,
       context.getPartitionId(),
       context.getRuleBase().getConfiguration().isMultithreadEvaluation());
   this.objectSource = source;
   this.leftTupleMemoryEnabled = context.isTupleMemoryEnabled();
   ObjectSource current = source;
   while (!(current instanceof ObjectTypeNode)) {
     current = current.getParentObjectSource();
   }
   ObjectTypeNode otn = (ObjectTypeNode) current;
   rootQueryNode = ClassObjectType.DroolsQuery_ObjectType.isAssignableFrom(otn.getObjectType());
 }
  public void testIsMemoryAllowedOverride() throws Exception {
    RuleBaseConfiguration config = new RuleBaseConfiguration();
    config.setAlphaMemory(true);
    ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(config);
    BuildContext buildContext =
        new BuildContext(ruleBase, ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator());
    ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();

    final Rule rule = new Rule("test-rule");
    final PropagationContext context =
        new PropagationContextImpl(0, PropagationContext.ASSERTION, null, null);

    final MockObjectSource source = new MockObjectSource(buildContext.getNextId());

    final ClassFieldExtractor extractor =
        cache.getExtractor(Cheese.class, "type", getClass().getClassLoader());

    final FieldValue field = FieldFactory.getFieldValue("cheddar");

    final Evaluator evaluator = ValueType.OBJECT_TYPE.getEvaluator(Operator.EQUAL);

    final LiteralConstraint constraint = new LiteralConstraint(extractor, evaluator, field);

    // With Memory
    buildContext.setAlphaNodeMemoryAllowed(false);
    final AlphaNode alphaNode =
        new AlphaNode(buildContext.getNextId(), constraint, source, buildContext); // has memory

    final MockObjectSink sink = new MockObjectSink();
    alphaNode.addObjectSink(sink);

    final Cheese cheddar = new Cheese("cheddar", 5);
    final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert(cheddar);

    // check sink is empty
    assertLength(0, sink.getAsserted());

    // check alpha memory is empty
    final AlphaMemory memory = (AlphaMemory) workingMemory.getNodeMemory(alphaNode);

    assertNull(memory.facts);

    // object should assert as it passes text
    alphaNode.assertObject(f0, context, workingMemory);

    assertEquals(1, sink.getAsserted().size());
    // memory should be one, as even though isAlphaMemory is on for the configuration, the build
    // never allows memory
    assertNull(memory.facts);
  }
 /**
  * Construct given a semantic <code>ObjectType</code> and the provided unique id. All <code>
  * ObjectTypdeNode</code> have node memory.
  *
  * @param id The unique id for the node.
  * @param objectType The semantic object-type differentiator.
  */
 public ObjectTypeNode(
     final int id,
     final EntryPointNode source,
     final ObjectType objectType,
     final BuildContext context) {
   super(
       id,
       context.getPartitionId(),
       context.getRuleBase().getConfiguration().isMultithreadEvaluation(),
       source,
       context.getRuleBase().getConfiguration().getAlphaNodeHashingThreshold());
   this.objectType = objectType;
   setObjectMemoryEnabled(context.isObjectTypeNodeMemoryEnabled());
 }
Exemple #10
0
  public BuildContext createContext() {

    RuleBaseConfiguration conf = new RuleBaseConfiguration();

    ReteooRuleBase rbase = new ReteooRuleBase("ID", conf);
    BuildContext buildContext = new BuildContext(rbase, rbase.getReteooBuilder().getIdGenerator());

    Rule rule = new Rule("rule1", "org.pkg1", null);
    org.drools.rule.Package pkg = new org.drools.rule.Package("org.pkg1");
    pkg.getDialectRuntimeRegistry().setDialectData("mvel", new MVELDialectRuntimeData());
    pkg.addRule(rule);
    buildContext.setRule(rule);

    return buildContext;
  }
Exemple #11
0
  public void attach(BuildContext context) {
    constraints.init(context, getType());
    setUnificationJoin();

    this.rightInput.addObjectSink(this);
    this.leftInput.addTupleSink(this, context);

    if (context == null) {
      return;
    }

    for (InternalWorkingMemory workingMemory : context.getWorkingMemories()) {
      final PropagationContext propagationContext =
          new PropagationContextImpl(
              workingMemory.getNextPropagationIdCounter(),
              PropagationContext.RULE_ADDITION,
              null,
              null,
              null);

      /* FIXME: This should be generalized at BetaNode level and the
       * instanceof should be removed!
       *
       * When L&R Unlinking is enabled, we only need to update the side
       * that is initially linked. If there are tuples to be propagated,
       * they will trigger the update (thus, population) of the other side.
       * */
      if (!lrUnlinkingEnabled || !(this instanceof JoinNode)) {

        this.rightInput.updateSink(this, propagationContext, workingMemory);
      }

      this.leftInput.updateSink(this, propagationContext, workingMemory);
    }
  }
Exemple #12
0
  public void setupJoinNode() {
    buildContext = createContext();

    joinNode =
        (JoinNode)
            BetaNodeBuilder.create(NodeTypeEnums.JoinNode, buildContext)
                .setLeftType(A.class)
                .setBinding("object", "$object")
                .setRightType(B.class)
                .setConstraint("object", "!=", "$object")
                .build();

    sinkNode = new JoinNode();
    sinkNode.setId(1);
    sinkNode.setConstraints(new EmptyBetaConstraints());

    joinNode.addTupleSink(sinkNode);

    wm = (InternalWorkingMemory) buildContext.getRuleBase().newStatefulSession(true);

    bm = (BetaMemory) wm.getNodeMemory(joinNode);

    bm0 = (BetaMemory) wm.getNodeMemory(sinkNode);

    smem = new SegmentMemory(joinNode);
    bm.setSegmentMemory(smem);

    smem0 = new SegmentMemory(sinkNode);
    bm0.setSegmentMemory(smem0);
    smem.add(smem0);
  }
 /**
  * Construct.
  *
  * @param id The unique id for this node.
  * @param leftInput The left input <code>TupleSource</code>.
  * @param rightInput The right input <code>ObjectSource</code>.
  * @param joinNodeBinder The constraints to be applied to the right objects
  */
 public ExistsNode(
     final int id,
     final LeftTupleSource leftInput,
     final ObjectSource rightInput,
     final BetaConstraints joinNodeBinder,
     final BuildContext context) {
   super(
       id,
       context.getPartitionId(),
       context.getRuleBase().getConfiguration().isMultithreadEvaluation(),
       leftInput,
       rightInput,
       joinNodeBinder,
       context);
   this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
 }
 public QueryElementNode(
     final int id,
     final LeftTupleSource tupleSource,
     final QueryElement queryElement,
     final boolean tupleMemoryEnabled,
     final boolean openQuery,
     final BuildContext context) {
   super(
       id,
       context.getPartitionId(),
       context.getRuleBase().getConfiguration().isMultithreadEvaluation());
   this.tupleSource = tupleSource;
   this.queryElement = queryElement;
   this.tupleMemoryEnabled = tupleMemoryEnabled;
   this.openQuery = openQuery;
   initMasks(context, tupleSource);
 }
  /**
   * Construct given a semantic <code>ObjectType</code> and the provided unique id. All <code>
   * ObjectTypdeNode</code> have node memory.
   *
   * @param id The unique id for the node.
   * @param objectType The semantic object-type differentiator.
   */
  public ObjectTypeNode(
      final int id,
      final EntryPointNode source,
      final ObjectType objectType,
      final BuildContext context) {
    super(
        id,
        context.getPartitionId(),
        context.getRuleBase().getConfiguration().isMultithreadEvaluation(),
        source,
        context.getRuleBase().getConfiguration().getAlphaNodeHashingThreshold());
    this.objectType = objectType;
    this.lrUnlinkingEnabled = context.getRuleBase().getConfiguration().isLRUnlinkingEnabled();
    setObjectMemoryEnabled(context.isObjectTypeNodeMemoryEnabled());

    if (ClassObjectType.DroolsQuery_ObjectType.isAssignableFrom(objectType)) {
      queryNode = true;
    }
  }
Exemple #16
0
  @Override
  protected void initDeclaredMask(BuildContext context, LeftTupleSource leftInput) {
    if (context == null || context.getLastBuiltPatterns() == null) {
      // only happens during unit tests
      rightDeclaredMask = Long.MAX_VALUE;
      super.initDeclaredMask(context, leftInput);
      return;
    }

    if (!(rightInput instanceof RightInputAdapterNode)) {
      Pattern pattern = context.getLastBuiltPatterns()[0]; // right input pattern
      ObjectType objectType = pattern.getObjectType();

      if (!(objectType instanceof ClassObjectType)) {
        // InitialFact has no type declaration and cannot be property specific
        // Only ClassObjectType can use property specific
        rightDeclaredMask = Long.MAX_VALUE;
      }

      Class objectClass = ((ClassObjectType) objectType).getClassType();
      if (isPropertyReactive(context, objectClass)) {
        rightListenedProperties = pattern.getListenedProperties();
        List<String> settableProperties = getSettableProperties(context.getRuleBase(), objectClass);
        rightDeclaredMask = calculatePositiveMask(rightListenedProperties, settableProperties);
        rightDeclaredMask |= constraints.getListenedPropertyMask(settableProperties);
        rightNegativeMask = calculateNegativeMask(rightListenedProperties, settableProperties);
      } else {
        // if property reactive is not on, then accept all modification propagations
        rightDeclaredMask = Long.MAX_VALUE;
      }
    } else {
      rightDeclaredMask = Long.MAX_VALUE;
      // There would have been no right input pattern, so swap current to first, so leftInput can
      // still work
      context.setLastBuiltPattern(context.getLastBuiltPatterns()[0]);
    }

    super.initDeclaredMask(context, leftInput);
  }
  public void testMemory() {
    RuleBaseConfiguration config = new RuleBaseConfiguration();
    config.setAlphaMemory(false);
    ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(config);
    BuildContext buildContext =
        new BuildContext(ruleBase, ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator());
    ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();

    final ClassFieldExtractor extractor =
        cache.getExtractor(Cheese.class, "type", getClass().getClassLoader());

    final FieldValue field = FieldFactory.getFieldValue("cheddar");

    final Evaluator evaluator = ValueType.OBJECT_TYPE.getEvaluator(Operator.EQUAL);

    final LiteralConstraint constraint = new LiteralConstraint(extractor, evaluator, field);

    final AlphaNode alphaNode =
        new AlphaNode(buildContext.getNextId(), constraint, null, buildContext);

    final AlphaMemory memory = (AlphaMemory) workingMemory.getNodeMemory(alphaNode);

    assertNotNull(memory);
  }
Exemple #18
0
 public AccumulateNode(
     final int id,
     final LeftTupleSource leftInput,
     final ObjectSource rightInput,
     final AlphaNodeFieldConstraint[] resultConstraints,
     final BetaConstraints sourceBinder,
     final BetaConstraints resultBinder,
     final Accumulate accumulate,
     final boolean unwrapRightObject,
     final BuildContext context) {
   super(
       id,
       context.getPartitionId(),
       context.getRuleBase().getConfiguration().isMultithreadEvaluation(),
       leftInput,
       rightInput,
       sourceBinder,
       context);
   this.resultBinder = resultBinder;
   this.resultConstraints = resultConstraints;
   this.accumulate = accumulate;
   this.unwrapRightObject = unwrapRightObject;
   this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
 }
  public void testUpdateSinkWithMemory() throws FactException, IntrospectionException {
    // An AlphaNode with memory should not try and repropagate from its source
    // Also it should only update the latest tuple sinky
    RuleBaseConfiguration config = new RuleBaseConfiguration();
    config.setAlphaMemory(true);
    ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(config);
    BuildContext buildContext =
        new BuildContext(ruleBase, ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator());
    ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();

    final Rule rule = new Rule("test-rule");
    final PropagationContext context =
        new PropagationContextImpl(0, PropagationContext.ASSERTION, null, null);

    final MockObjectSource source = new MockObjectSource(buildContext.getNextId());

    final FieldExtractor extractor =
        cache.getExtractor(Cheese.class, "type", getClass().getClassLoader());

    final FieldValue field = FieldFactory.getFieldValue("cheddar");

    final Evaluator evaluator = ValueType.OBJECT_TYPE.getEvaluator(Operator.EQUAL);

    final LiteralConstraint constraint = new LiteralConstraint(extractor, evaluator, field);

    buildContext.setAlphaNodeMemoryAllowed(true);
    final AlphaNode alphaNode =
        new AlphaNode(buildContext.getNextId(), constraint, source, buildContext); // has memory

    alphaNode.attach();

    final MockObjectSink sink1 = new MockObjectSink();
    alphaNode.addObjectSink(sink1);

    // Assert a single fact which should be in the AlphaNode memory and also
    // propagated to the
    // the tuple sink
    final Cheese cheese = new Cheese("cheddar", 0);
    final DefaultFactHandle handle1 = new DefaultFactHandle(1, cheese);

    alphaNode.assertObject(handle1, context, workingMemory);

    // Create a fact that should not be propagated, since the alpha node restriction will filter it
    // out
    final Cheese stilton = new Cheese("stilton", 10);
    final DefaultFactHandle handle2 = new DefaultFactHandle(2, stilton);
    // adding handle to the mock source
    source.addFact(handle2);

    alphaNode.assertObject(handle2, context, workingMemory);
    assertLength(1, sink1.getAsserted());

    // Attach a new tuple sink
    final MockObjectSink sink2 = new MockObjectSink();

    // Tell the alphanode to update the new node. Make sure the first sink1
    // is not updated
    // likewise the source should not do anything
    alphaNode.updateSink(sink2, context, workingMemory);

    assertLength(1, sink1.getAsserted());
    assertLength(1, sink2.getAsserted());
    assertEquals(0, source.getUdated());
  }
  /**
   * Test just tuple assertions
   *
   * @throws AssertionException
   */
  @Test
  public void testAssertTupleSequentialMode() throws Exception {
    RuleBaseConfiguration conf = new RuleBaseConfiguration();
    conf.setSequential(true);

    ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
    BuildContext buildContext =
        new BuildContext(ruleBase, ruleBase.getReteooBuilder().getIdGenerator());
    buildContext.setTupleMemoryEnabled(false);
    // overide the original node, so we an set the BuildContext
    this.node =
        new AccumulateNode(
            15,
            this.tupleSource,
            this.objectSource,
            new AlphaNodeFieldConstraint[0],
            EmptyBetaConstraints.getInstance(),
            EmptyBetaConstraints.getInstance(),
            this.accumulate,
            false,
            buildContext);

    this.node.addTupleSink(this.sink);

    this.workingMemory =
        new ReteooWorkingMemory(1, (ReteooRuleBase) RuleBaseFactory.newRuleBase(conf));

    this.memory = ((AccumulateMemory) this.workingMemory.getNodeMemory(this.node)).betaMemory;

    final DefaultFactHandle f0 =
        (DefaultFactHandle)
            this.workingMemory.getFactHandleFactory().newFactHandle("cheese", null, null, null);
    final DefaultFactHandle f1 =
        (DefaultFactHandle)
            this.workingMemory
                .getFactHandleFactory()
                .newFactHandle("other cheese", null, null, null);

    final LeftTupleImpl tuple0 = new LeftTupleImpl(f0, null, true);

    this.node.assertObject(f0, this.context, this.workingMemory);
    this.node.assertObject(f1, this.context, this.workingMemory);

    // assert tuple, should not add to left memory, since we are in sequential mode
    this.node.assertLeftTuple(
        tuple0,
        new PropagationContextImpl(0, PropagationContext.ASSERTION, null, null, f0),
        this.workingMemory);
    // check memories
    assertNull(this.memory.getLeftTupleMemory());
    assertEquals(2, this.memory.getRightTupleMemory().size());
    assertEquals(
        "Wrong number of elements in matching objects list ",
        2,
        this.accumulator.getMatchingObjects().size());

    // assert tuple, should not add left memory
    final LeftTupleImpl tuple1 = new LeftTupleImpl(f1, null, true);
    this.node.assertLeftTuple(
        tuple1,
        new PropagationContextImpl(0, PropagationContext.ASSERTION, null, null, f1),
        this.workingMemory);
    assertNull(this.memory.getLeftTupleMemory());
    assertEquals(
        "Wrong number of elements in matching objects list ",
        2,
        this.accumulator.getMatchingObjects().size());

    assertEquals("Two tuples should have been propagated", 2, this.sink.getAsserted().size());
  }
  public void execute(Map<String, Object> context, List<String[]> args) {
    BuildContext buildContext = (BuildContext) context.get("BuildContext");

    if (args.size() >= 1) {

      // The first argument list is the node parameters
      String[] a = args.get(0);
      String name = a[0];
      String leftInput = a[1];
      String rightInput = a[2];
      String sourceType = a[3];
      String expr = a[4];

      LeftTupleSource leftTupleSource;
      if ("mock".equals(leftInput)) {
        leftTupleSource = Mockito.mock(LeftTupleSource.class);
      } else {
        leftTupleSource = (LeftTupleSource) context.get(leftInput);
      }

      ObjectSource rightObjectSource;
      if ("mock".equals(rightInput)) {
        rightObjectSource = Mockito.mock(ObjectSource.class);
      } else {
        rightObjectSource = (ObjectSource) context.get(rightInput);
      }

      Pattern sourcePattern;
      Pattern resultPattern;
      try {
        sourcePattern = reteTesterHelper.getPattern(0, sourceType);

        // we always use the accumulate function "sum", so return type is always Number
        resultPattern =
            reteTesterHelper.getPattern(buildContext.getNextId(), Number.class.getName());
      } catch (Exception e) {
        throw new IllegalArgumentException(
            "Not possible to process arguments: " + Arrays.toString(a));
      }

      BetaConstraints betaSourceConstraints = new EmptyBetaConstraints();
      AlphaNodeFieldConstraint[] alphaResultConstraint = new AlphaNodeFieldConstraint[0];
      // the following arguments are constraints
      for (int i = 1; i < args.size(); i++) {
        a = args.get(i);
        String type = a[0];
        String fieldName = a[1];
        String operator = a[2];
        String val = a[3];

        if ("source".equals(type)) {
          Declaration declr = (Declaration) context.get(val);
          try {
            BetaNodeFieldConstraint sourceBetaConstraint =
                this.reteTesterHelper.getBoundVariableConstraint(
                    sourcePattern, fieldName, declr, operator);
            betaSourceConstraints =
                new SingleBetaConstraints(
                    sourceBetaConstraint, buildContext.getRuleBase().getConfiguration());
          } catch (IntrospectionException e) {
            throw new IllegalArgumentException();
          }
        } else if ("result".equals(type)) {
          alphaResultConstraint = new AlphaNodeFieldConstraint[1];
          try {
            alphaResultConstraint[0] =
                this.reteTesterHelper.getLiteralConstraint(resultPattern, fieldName, operator, val);
          } catch (IntrospectionException e) {
            throw new IllegalArgumentException(
                "Unable to configure alpha constraint: " + Arrays.toString(a), e);
          }
        }
      }

      NodeTestCase testCase = (NodeTestCase) context.get("TestCase");
      List<String> classImports = new ArrayList<String>();
      List<String> pkgImports = new ArrayList<String>();
      for (String imp : testCase.getImports()) {
        if (imp.endsWith(".*")) {
          pkgImports.add(imp.substring(0, imp.lastIndexOf('.')));
        } else {
          classImports.add(imp);
        }
      }

      // build an external function executor
      MVELCompilationUnit compilationUnit =
          new MVELCompilationUnit(
              name,
              expr,
              pkgImports.toArray(new String[0]), // pkg imports
              classImports.toArray(new String[0]), // imported classes
              new String[] {}, // imported methods
              new String[] {}, // imported fields
              new String[] {}, // global identifiers
              new Declaration[] {}, // previous declarations
              new Declaration[] {(Declaration) context.get(expr)}, // local declarations
              new String[] {}, // other identifiers
              new String[] {}, // input identifiers
              new String[] {}, // input types
              4,
              false);

      AccumulateFunction accFunction = new SumAccumulateFunction();

      Accumulator accumulator = new MVELAccumulatorFunctionExecutor(compilationUnit, accFunction);
      ((MVELCompileable) accumulator).compile(Thread.currentThread().getContextClassLoader());

      Accumulate accumulate =
          new Accumulate(
              sourcePattern,
              new Declaration[] {}, // required declaration
              new Declaration[] {}, // inner declarations
              new Accumulator[] {accumulator});
      AccumulateNode accNode =
          new AccumulateNode(
              buildContext.getNextId(),
              leftTupleSource,
              rightObjectSource,
              alphaResultConstraint,
              betaSourceConstraints,
              new EmptyBetaConstraints(),
              new Behavior[] {},
              accumulate,
              false,
              buildContext);

      accNode.attach();
      context.put(name, accNode);

    } else {
      StringBuilder msgBuilder = new StringBuilder();
      msgBuilder.append("Can not parse AccumulateNode step arguments: \n");
      for (String[] arg : args) {
        msgBuilder.append("    ");
        msgBuilder.append(Arrays.toString(arg));
        msgBuilder.append("\n");
      }
      throw new IllegalArgumentException(msgBuilder.toString());
    }
  }
 public static boolean isPropertyReactive(BuildContext context, Class<?> objectClass) {
   TypeDeclaration typeDeclaration = context.getRuleBase().getTypeDeclaration(objectClass);
   return typeDeclaration != null && typeDeclaration.isPropertyReactive();
 }
Exemple #23
0
  @Test
  public void testUpdateSinkWithoutMemory() throws FactException, IntrospectionException {
    // An AlphaNode should try and repropagate from its source
    ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
    BuildContext buildContext =
        new BuildContext(ruleBase, ((ReteooRuleBase) ruleBase).getReteooBuilder().getIdGenerator());
    ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) ruleBase.newStatefulSession();

    final Rule rule = new Rule("test-rule");
    final PropagationContext context =
        new PropagationContextImpl(0, PropagationContext.INSERTION, null, null, null);

    final MockObjectSource source = new MockObjectSource(buildContext.getNextId());

    final InternalReadAccessor extractor =
        store.getReader(Cheese.class, "type", getClass().getClassLoader());

    final FieldValue field = FieldFactory.getInstance().getFieldValue("cheddar");

    final MvelConstraint constraint =
        new MvelConstraintTestUtil("type == \"cheddar\"", field, extractor);

    final AlphaNode alphaNode =
        new AlphaNode(buildContext.getNextId(), constraint, source, buildContext); // no memory

    alphaNode.attach();

    final MockObjectSink sink1 = new MockObjectSink();
    alphaNode.addObjectSink(sink1);

    // Assert a single fact which should be in the AlphaNode memory and also
    // propagated to the
    // the tuple sink
    final Cheese cheese = new Cheese("cheddar", 0);
    final DefaultFactHandle handle1 = new DefaultFactHandle(1, cheese);
    // adding handle to the mock source
    source.addFact(handle1);

    alphaNode.assertObject(handle1, context, workingMemory);

    // Create a fact that should not be propagated, since the alpha node restriction will filter it
    // out
    final Cheese stilton = new Cheese("stilton", 10);
    final DefaultFactHandle handle2 = new DefaultFactHandle(2, stilton);
    // adding handle to the mock source
    source.addFact(handle2);

    alphaNode.assertObject(handle2, context, workingMemory);

    assertLength(1, sink1.getAsserted());

    // Attach a new tuple sink
    final MockObjectSink sink2 = new MockObjectSink();

    // Tell the alphanode to update the new node. Make sure the first sink1
    // is not updated
    // likewise the source should not do anything
    alphaNode.updateSink(sink2, context, workingMemory);

    assertLength(1, sink1.getAsserted());
    assertLength(1, sink2.getAsserted());
    assertEquals(1, source.getUdated());
  }
  public void testQueryTerminalNode() {
    final ClassObjectType queryObjectType = new ClassObjectType(DroolsQuery.class);
    final ObjectTypeNode queryObjectTypeNode =
        new ObjectTypeNode(this.buildContext.getNextId(), queryObjectType, buildContext);
    queryObjectTypeNode.attach();

    ClassFieldExtractor extractor =
        cache.getExtractor(DroolsQuery.class, "name", DroolsQuery.class.getClassLoader());

    FieldValue field = FieldFactory.getFieldValue("query-1");

    final Evaluator evaluator = ValueType.STRING_TYPE.getEvaluator(Operator.EQUAL);
    LiteralConstraint constraint = new LiteralConstraint(extractor, evaluator, field);

    AlphaNode alphaNode =
        new AlphaNode(this.buildContext.getNextId(), constraint, queryObjectTypeNode, buildContext);
    alphaNode.attach();

    final LeftInputAdapterNode liaNode =
        new LeftInputAdapterNode(this.buildContext.getNextId(), alphaNode, this.buildContext);
    liaNode.attach();

    final ClassObjectType cheeseObjectType = new ClassObjectType(Cheese.class);
    final ObjectTypeNode cheeseObjectTypeNode =
        new ObjectTypeNode(this.buildContext.getNextId(), cheeseObjectType, buildContext);
    cheeseObjectTypeNode.attach();

    extractor = cache.getExtractor(Cheese.class, "type", getClass().getClassLoader());

    field = FieldFactory.getFieldValue("stilton");

    constraint = new LiteralConstraint(extractor, evaluator, field);

    alphaNode =
        new AlphaNode(
            this.buildContext.getNextId(), constraint, cheeseObjectTypeNode, buildContext);
    alphaNode.attach();

    BuildContext buildContext =
        new BuildContext(ruleBase, ruleBase.getReteooBuilder().getIdGenerator());
    buildContext.setTupleMemoryEnabled(false);

    final JoinNode joinNode =
        new JoinNode(
            this.buildContext.getNextId(),
            liaNode,
            alphaNode,
            EmptyBetaConstraints.getInstance(),
            buildContext);
    joinNode.attach();

    final Query query = new Query("query-1");

    final QueryTerminalNode queryNode =
        new QueryTerminalNode(this.buildContext.getNextId(), joinNode, query, query.getLhs());

    queryNode.attach();

    final org.drools.rule.Package pkg = new org.drools.rule.Package("com.drools.test");
    pkg.addRule(query);

    try {
      final Field pkgField = ruleBase.getClass().getSuperclass().getDeclaredField("pkgs");
      pkgField.setAccessible(true);
      final Map pkgs = (Map) pkgField.get(ruleBase);
      pkgs.put(pkg.getName(), pkg);
    } catch (final Exception e) {
      Assert.fail("Should not throw any exception: " + e.getMessage());
    }

    final WorkingMemory workingMemory = ruleBase.newStatefulSession();
    QueryResults results = workingMemory.getQueryResults("query-1");

    assertEquals(0, results.size());

    final Cheese stilton1 = new Cheese("stilton", 100);
    final FactHandle handle1 = workingMemory.insert(stilton1);

    results = workingMemory.getQueryResults("query-1");

    assertEquals(1, results.size());

    final Cheese cheddar = new Cheese("cheddar", 55);
    workingMemory.insert(cheddar);

    results = workingMemory.getQueryResults("query-1");

    assertEquals(1, results.size());

    final Cheese stilton2 = new Cheese("stilton", 5);

    final FactHandle handle2 = workingMemory.insert(stilton2);

    results = workingMemory.getQueryResults("query-1");

    assertEquals(2, results.size());

    QueryResult result = results.get(0);
    assertEquals(1, result.size());
    assertEquals(stilton2, result.get(0));

    result = results.get(1);
    assertEquals(1, result.size());
    assertEquals(stilton1, result.get(0));

    int i = 0;
    for (final Iterator it = results.iterator(); it.hasNext(); ) {
      result = (QueryResult) it.next();
      assertEquals(1, result.size());
      if (i == 1) {
        assertSame(stilton1, result.get(0));
      } else {
        assertSame(stilton2, result.get(0));
      }
      i++;
    }

    workingMemory.retract(handle1);
    results = workingMemory.getQueryResults("query-1");

    assertEquals(1, results.size());

    workingMemory.retract(handle2);
    results = workingMemory.getQueryResults("query-1");

    assertEquals(0, results.size());
  }
  public static ReteooStatefulSession readSession(
      ReteooStatefulSession session,
      DefaultAgenda agenda,
      long time,
      boolean multithread,
      MarshallerReaderContext context)
      throws IOException, ClassNotFoundException {
    if (session.getTimerService() instanceof PseudoClockScheduler) {
      PseudoClockScheduler clock = (PseudoClockScheduler) session.getTimerService();
      clock.advanceTime(time, TimeUnit.MILLISECONDS);
    }

    // RuleFlowGroups need to reference the session
    for (RuleFlowGroup group : agenda.getRuleFlowGroupsMap().values()) {
      ((RuleFlowGroupImpl) group).setWorkingMemory(session);
    }

    context.wm = session;

    context.handles.put(
        context.wm.getInitialFactHandle().getId(), context.wm.getInitialFactHandle());

    if (context.stream.readBoolean()) {
      InternalFactHandle initialFactHandle = context.wm.getInitialFactHandle();
      int sinkId = context.stream.readInt();
      ObjectTypeNode initialFactNode = (ObjectTypeNode) context.sinks.get(sinkId);
      if (initialFactNode == null) {
        // ------ START RANT ------
        // The following code is as bad as it looks, but since I was so far
        // unable to convince Mark that creating OTNs on demand is really bad,
        // I have to continue doing it :)
        EntryPointNode defaultEPNode =
            context.ruleBase.getRete().getEntryPointNode(EntryPoint.DEFAULT);
        BuildContext buildContext =
            new BuildContext(
                context.ruleBase, context.ruleBase.getReteooBuilder().getIdGenerator());
        buildContext.setPartitionId(RuleBasePartitionId.MAIN_PARTITION);
        buildContext.setObjectTypeNodeMemoryEnabled(true);
        initialFactNode =
            new ObjectTypeNode(
                sinkId, defaultEPNode, ClassObjectType.InitialFact_ObjectType, buildContext);
        // isn't contention something everybody loves?
        context.ruleBase.lock();
        try {
          // Yeah, I know, because one session is being deserialized, we go and lock all of them...
          initialFactNode.attach(buildContext);
        } finally {
          context.ruleBase.unlock();
        }
        // ------- END RANT -----
      }
      ObjectHashSet initialFactMemory = (ObjectHashSet) context.wm.getNodeMemory(initialFactNode);

      initialFactMemory.add(initialFactHandle);
      readRightTuples(initialFactHandle, context);
    }
    while (context.readShort() == PersisterEnums.ENTRY_POINT) {
      String entryPointId = context.stream.readUTF();
      WorkingMemoryEntryPoint wmep = context.wm.getEntryPoints().get(entryPointId);
      readFactHandles(context, ((NamedEntryPoint) wmep).getObjectStore());
    }
    InternalFactHandle handle = context.wm.getInitialFactHandle();
    while (context.stream.readShort() == PersisterEnums.LEFT_TUPLE) {
      LeftTupleSink sink = (LeftTupleSink) context.sinks.get(context.stream.readInt());
      LeftTuple leftTuple = sink.createLeftTuple(handle, sink, true);
      readLeftTuple(leftTuple, context);
    }

    readPropagationContexts(context);

    readActivations(context);

    readActionQueue(context);

    readTruthMaintenanceSystem(context);

    if (processMarshaller != null) {
      processMarshaller.readProcessInstances(context);
    } else {
      short type = context.stream.readShort();
      if (PersisterEnums.END != type) {
        throw new IllegalStateException(
            "No process marshaller, unable to unmarshall type: " + type);
      }
    }

    if (processMarshaller != null) {
      processMarshaller.readWorkItems(context);
    } else {
      short type = context.stream.readShort();
      if (PersisterEnums.END != type) {
        throw new IllegalStateException(
            "No process marshaller, unable to unmarshall type: " + type);
      }
    }

    if (processMarshaller != null) {
      // This actually does ALL timers, due to backwards compatability issues
      // It will read in old JBPM binaries, but always write to the new binary format.
      processMarshaller.readProcessTimers(context);
    } else {
      short type = context.stream.readShort();
      if (PersisterEnums.END != type) {
        throw new IllegalStateException(
            "No process marshaller, unable to unmarshall type: " + type);
      }
    }

    // no legacy jBPM timers, so handle locally
    while (context.readShort() == PersisterEnums.DEFAULT_TIMER) {
      InputMarshaller.readTimer(context);
    }

    if (multithread) {
      session.startPartitionManagers();
    }

    return session;
  }