/**
   *
   *
   * <pre>
   *
   *
   *                ( Cheese (type &quot;cheddar&quot;) )
   *
   *
   * </pre>
   *
   * This is currently the same as using a ReturnValueConstraint just that it doesn't need any
   * requiredDeclarations
   *
   * @throws IntrospectionException
   */
  public void testLiteralConstraint() throws IntrospectionException {
    final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
    final InternalWorkingMemory workingMemory =
        (InternalWorkingMemory) ruleBase.newStatefulSession();

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

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

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

    final LiteralConstraint constraint = new LiteralConstraint(extractor, evaluator, field);
    final ContextEntry context = constraint.createContextEntry();

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

    final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert(cheddar);

    // check constraint
    assertTrue(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context));

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

    final InternalFactHandle stiltonHandle = (InternalFactHandle) workingMemory.insert(stilton);

    // check constraint
    assertFalse(constraint.isAllowed(stiltonHandle.getObject(), workingMemory, context));
  }
Example #2
0
  private void addMatch(
      final LeftTuple leftTuple,
      final RightTuple rightTuple,
      final LeftTuple currentLeftChild,
      final LeftTuple currentRightChild,
      final InternalWorkingMemory workingMemory,
      final AccumulateMemory memory,
      final AccumulateContext accresult,
      final boolean useLeftMemory) {
    LeftTuple tuple = leftTuple;
    InternalFactHandle handle = rightTuple.getFactHandle();
    if (this.unwrapRightObject) {
      // if there is a subnetwork, handle must be unwrapped
      tuple = (LeftTuple) handle.getObject();
      // handle = tuple.getLastHandle();
    }
    this.accumulate.accumulate(
        memory.workingMemoryContext, accresult.context, tuple, handle, workingMemory);

    // in sequential mode, we don't need to keep record of matched tuples
    if (useLeftMemory) {
      // linking left and right by creating a new left tuple
      createLeftTuple(leftTuple, rightTuple, currentLeftChild, currentRightChild, this, true);
    }
  }
Example #3
0
  /**
   * Removes a match between left and right tuple
   *
   * @param rightTuple
   * @param match
   * @param result
   */
  private void removeMatch(
      final RightTuple rightTuple,
      final LeftTuple match,
      final InternalWorkingMemory workingMemory,
      final AccumulateMemory memory,
      final AccumulateContext accctx,
      final boolean reaccumulate) {
    // save the matching tuple
    LeftTuple leftTuple = match.getLeftParent();

    if (match != null) {
      // removing link between left and right
      match.unlinkFromLeftParent();
      match.unlinkFromRightParent();
    }

    // if there is a subnetwork, we need to unwrap the object from inside the tuple
    InternalFactHandle handle = rightTuple.getFactHandle();
    LeftTuple tuple = leftTuple;
    if (this.unwrapRightObject) {
      tuple = (LeftTuple) handle.getObject();
      // handle = tuple.getLastHandle();
    }

    if (this.accumulate.supportsReverse()) {
      // just reverse this single match
      this.accumulate.reverse(
          memory.workingMemoryContext, accctx.context, tuple, handle, workingMemory);
    } else {
      // otherwise need to recalculate all matches for the given leftTuple
      if (reaccumulate) {
        reaccumulateForLeftTuple(leftTuple, workingMemory, memory, accctx);
      }
    }
  }
  public static void readTruthMaintenanceSystem(MarshallerReaderContext context)
      throws IOException {
    ObjectInputStream stream = context.stream;

    TruthMaintenanceSystem tms = context.wm.getTruthMaintenanceSystem();
    while (stream.readShort() == PersisterEnums.EQUALITY_KEY) {
      int status = stream.readInt();
      int factHandleId = stream.readInt();
      InternalFactHandle handle = (InternalFactHandle) context.handles.get(factHandleId);

      // ObjectTypeConf state is not marshalled, so it needs to be re-determined
      ObjectTypeConf typeConf =
          context
              .wm
              .getObjectTypeConfigurationRegistry()
              .getObjectTypeConf(context.wm.getEntryPoint(), handle.getObject());
      if (!typeConf.isTMSEnabled()) {
        typeConf.enableTMS();
      }

      EqualityKey key = new EqualityKey(handle, status);
      handle.setEqualityKey(key);
      while (stream.readShort() == PersisterEnums.FACT_HANDLE) {
        factHandleId = stream.readInt();
        handle = (InternalFactHandle) context.handles.get(factHandleId);
        key.addFactHandle(handle);
        handle.setEqualityKey(key);
      }
      tms.put(key);
    }
  }
Example #5
0
 public static Map<String, Object> valuesAsMap(
     Object object,
     InternalWorkingMemory workingMemory,
     LeftTuple leftTuple,
     Declaration[] declarations) {
   if (declarations.length == 0) {
     return null;
   }
   Map<String, Object> map = new HashMap<String, Object>();
   for (Declaration declaration : declarations) {
     if (leftTuple == null) {
       map.put(
           declaration.getBindingName(),
           declaration.getExtractor().getValue(workingMemory, object));
     } else {
       InternalFactHandle fact = leftTuple.get(declaration);
       map.put(
           declaration.getBindingName(),
           declaration
               .getExtractor()
               .getValue(workingMemory, fact != null ? fact.getObject() : object));
     }
   }
   return map;
 }
Example #6
0
  /**
   * Propagate the <code>FactHandleimpl</code> through the <code>Rete</code> network. All <code>
   * FactHandleImpl</code> should be remembered in the node memory, so that later runtime rule
   * attachmnents can have the matched facts propagated to them.
   *
   * @param factHandle The fact handle.
   * @param object The object to assert.
   * @param workingMemory The working memory session.
   */
  public void assertObject(
      final InternalFactHandle factHandle,
      final PropagationContext context,
      final InternalWorkingMemory workingMemory) {

    if (objectMemoryEnabled && !(queryNode && !((DroolsQuery) factHandle.getObject()).isOpen())) {
      final ObjectHashSet memory = (ObjectHashSet) workingMemory.getNodeMemory(this);
      memory.add(factHandle, false);
    }

    if (compiledNetwork != null) {
      compiledNetwork.assertObject(factHandle, context, workingMemory);
    } else {

      context.setCurrentPropagatingOTN(this);
      this.sink.propagateAssertObject(factHandle, context, workingMemory);
    }

    if (this.objectType.isEvent()
        && this.expirationOffset >= 0
        && this.expirationOffset != Long.MAX_VALUE) {
      // schedule expiration
      WorkingMemoryReteExpireAction expire = new WorkingMemoryReteExpireAction(factHandle, this);
      TimerService clock = workingMemory.getTimerService();

      long nextTimestamp =
          Math.max(
              clock.getCurrentTime() + this.expirationOffset,
              ((EventFactHandle) factHandle).getStartTimestamp() + this.expirationOffset);
      JobContext jobctx = new ExpireJobContext(expire, workingMemory);
      JobHandle handle =
          clock.scheduleJob(job, jobctx, new PointInTimeTrigger(nextTimestamp, null, null));
      jobctx.setJobHandle(handle);
    }
  }
  public static void readFactHandles(MarshallerReaderContext context, ObjectStore objectStore)
      throws IOException, ClassNotFoundException {
    ObjectInputStream stream = context.stream;
    InternalWorkingMemory wm = context.wm;

    int size = stream.readInt();

    // load the handles
    InternalFactHandle[] handles = new InternalFactHandle[size];
    for (int i = 0; i < size; i++) {
      InternalFactHandle handle = readFactHandle(context);

      context.handles.put(handle.getId(), handle);
      handles[i] = handle;

      if (handle.getObject() != null) {
        objectStore.addHandle(handle, handle.getObject());
      }

      readRightTuples(handle, context);
    }

    readLeftTuples(context); // object store

    if (stream.readBoolean()) {
      readLeftTuples(context); // activation fact handles
    }

    // add handles to object type nodes
    for (InternalFactHandle factHandle : handles) {
      Object object = factHandle.getObject();

      EntryPoint ep =
          ((InternalWorkingMemoryEntryPoint) factHandle.getEntryPoint()).getEntryPoint();

      ObjectTypeConf typeConf =
          ((InternalWorkingMemoryEntryPoint) factHandle.getEntryPoint())
              .getObjectTypeConfigurationRegistry()
              .getObjectTypeConf(ep, object);
      ObjectTypeNode[] cachedNodes = typeConf.getObjectTypeNodes();
      for (int i = 0, length = cachedNodes.length; i < length; i++) {
        ObjectHashSet set = (ObjectHashSet) wm.getNodeMemory(cachedNodes[i]);
        set.add(factHandle, false);
      }
    }
  }
 private static ProtobufMessages.FactHandle.HandleType getHandleType(InternalFactHandle handle) {
   if (handle instanceof EventFactHandle) {
     return ProtobufMessages.FactHandle.HandleType.EVENT;
   } else if (handle instanceof QueryElementFactHandle) {
     return ProtobufMessages.FactHandle.HandleType.QUERY;
   } else if (handle.getObject() instanceof InitialFact) {
     return ProtobufMessages.FactHandle.HandleType.INITIAL_FACT;
   }
   return ProtobufMessages.FactHandle.HandleType.FACT;
 }
    public boolean evaluateCachedRight(
        InternalWorkingMemory workingMemory,
        VariableContextEntry context,
        InternalFactHandle left) {

      Object target = left.getObject();
      Object source = context.getObject();

      return compare(source, target, workingMemory);
    }
    public boolean evaluateCachedLeft(
        InternalWorkingMemory workingMemory,
        VariableContextEntry context,
        InternalFactHandle right) {

      Object target = ((VariableRestriction.ObjectVariableContextEntry) context).left;
      Object source = right.getObject();

      return compare(source, target, workingMemory);
    }
Example #11
0
 public void accumulate(
     Object workingMemoryContext,
     Object context,
     Tuple leftTuple,
     InternalFactHandle handle,
     Declaration[] declarations,
     Declaration[] innerDeclarations,
     WorkingMemory workingMemory)
     throws Exception {
   this.matchingObjects.add(handle.getObject());
 }
    public boolean evaluate(
        InternalWorkingMemory workingMemory,
        final InternalReadAccessor extractor1,
        final InternalFactHandle handle1,
        final InternalReadAccessor extractor2,
        final InternalFactHandle handle2) {
      if (extractor1.isNullValue(workingMemory, handle1.getObject())
          || extractor2.isNullValue(workingMemory, handle2.getObject())) {
        return false;
      }

      long distStart =
          ((EventFactHandle) handle1).getStartTimestamp()
              - ((EventFactHandle) handle2).getStartTimestamp();
      long distEnd =
          Math.abs(
              ((EventFactHandle) handle2).getEndTimestamp()
                  - ((EventFactHandle) handle1).getEndTimestamp());
      return this.getOperator().isNegated() ^ (distStart > 0 && distEnd <= this.endDev);
    }
Example #13
0
  private static void writeFactHandle(
      MarshallerWriteContext context,
      ObjectOutputStream stream,
      ObjectMarshallingStrategyStore objectMarshallingStrategyStore,
      int type,
      InternalFactHandle handle)
      throws IOException {
    stream.writeInt(type);
    stream.writeInt(handle.getId());
    stream.writeLong(handle.getRecency());

    if (type == 2) {
      // is event
      EventFactHandle efh = (EventFactHandle) handle;
      stream.writeLong(efh.getStartTimestamp());
      stream.writeLong(efh.getDuration());
      stream.writeBoolean(efh.isExpired());
      stream.writeLong(efh.getActivationsCount());
    }

    // context.out.println( "Object : int:" + handle.getId() + " long:" + handle.getRecency() );
    // context.out.println( handle.getObject() );

    Object object = handle.getObject();

    // Old versions wrote -1 and tested >= 0 to see if there was a strategy available
    // Now, we write -2 to indicate that we write the strategy class name to the stream
    stream.writeInt(-2);
    if (object != null) {
      ObjectMarshallingStrategy strategy = objectMarshallingStrategyStore.getStrategyObject(object);

      String strategyClassName = strategy.getClass().getName();
      stream.writeUTF(strategyClassName);

      strategy.write(stream, object);
    } else {
      stream.writeUTF("");
    }

    if (handle.getEntryPoint() instanceof InternalWorkingMemoryEntryPoint) {
      String entryPoint =
          ((InternalWorkingMemoryEntryPoint) handle.getEntryPoint())
              .getEntryPoint()
              .getEntryPointId();
      if (entryPoint != null && !entryPoint.equals("")) {
        stream.writeBoolean(true);
        stream.writeUTF(entryPoint);
      } else {
        stream.writeBoolean(false);
      }
    } else {
      stream.writeBoolean(false);
    }
  }
 public boolean isAllowedCachedLeft(ContextEntry context, InternalFactHandle handle) {
   if (((UnificationContextEntry) context).getVariable() == null) {
     return this.vr.isAllowedCachedLeft(
         ((UnificationContextEntry) context).getContextEntry(), handle);
   } else {
     VariableContextEntry vContext =
         (VariableContextEntry) ((UnificationContextEntry) context).getContextEntry();
     ((UnificationContextEntry) context)
         .getVariable()
         .setValue(vContext.getFieldExtractor().getValue(handle.getObject()));
     return true;
   }
 }
Example #15
0
    public void rowUpdated(
        final Rule rule,
        final LeftTuple resultLeftTuple,
        final PropagationContext context,
        final InternalWorkingMemory workingMemory) {
      RightTuple rightTuple = (RightTuple) resultLeftTuple.getObject();
      if (rightTuple.getMemory() != null) {
        // Already sheduled as an insert
        return;
      }

      rightTuple.setLeftTuple(null);
      resultLeftTuple.setObject(null);

      // We need to recopy everything back again, as we don't know what has or hasn't changed
      QueryTerminalNode node = (QueryTerminalNode) resultLeftTuple.getLeftTupleSink();
      Declaration[] decls = node.getDeclarations();
      InternalFactHandle rootHandle = resultLeftTuple.get(0);
      DroolsQuery query = (DroolsQuery) rootHandle.getObject();

      Object[] objects = new Object[query.getElements().length];

      Declaration decl;
      for (int i = 0, length = this.variables.length; i < length; i++) {
        decl = decls[this.variables[i]];
        objects[this.variables[i]] =
            decl.getValue(workingMemory, resultLeftTuple.get(decl).getObject());
      }

      QueryElementFactHandle handle = (QueryElementFactHandle) rightTuple.getFactHandle();

      handle.setRecency(workingMemory.getFactHandleFactory().getAtomicRecency().incrementAndGet());
      handle.setObject(objects);

      if (query.isOpen()) {
        rightTuple.setLeftTuple(resultLeftTuple);
        resultLeftTuple.setObject(rightTuple);
      }

      // Don't need to recreate child links, as they will already be there form the first "add"

      RightTupleList rightTuples = query.getResultUpdateRightTupleList();
      if (rightTuples == null) {
        rightTuples = new RightTupleList();
        query.setResultUpdateRightTupleList(rightTuples);
        QueryResultUpdateAction updateAction =
            new QueryResultUpdateAction(context, this.factHandle, leftTuple, this.node);
        context.getQueue2().addFirst(updateAction);
      }
      rightTuples.add(rightTuple);
    }
Example #16
0
  public static void writeFactHandles(MarshallerWriteContext context, ObjectStore objectStore)
      throws IOException {
    ObjectOutputStream stream = context.stream;
    InternalWorkingMemory wm = context.wm;
    ObjectMarshallingStrategyStore objectMarshallingStrategyStore =
        context.objectMarshallingStrategyStore;

    List<InternalFactHandle> matchFactHandles = null;

    if (((InternalAgenda) wm.getAgenda()).isDeclarativeAgenda()) {
      ActivationIterator it = ActivationIterator.iterator(wm);
      matchFactHandles = new ArrayList<InternalFactHandle>(100);
      for (Activation item = (Activation) it.next(); item != null; item = (Activation) it.next()) {
        matchFactHandles.add(item.getFactHandle());
      }
    }

    stream.writeInt(
        objectStore.size() + ((matchFactHandles == null) ? 0 : matchFactHandles.size()));

    // Write out FactHandles
    for (InternalFactHandle handle : orderFacts(objectStore)) {
      // stream.writeShort( PersisterEnums.FACT_HANDLE );
      // InternalFactHandle handle = (InternalFactHandle) it.next();
      writeFactHandle(context, stream, objectMarshallingStrategyStore, handle);

      writeRightTuples(handle, context);
    }

    if (matchFactHandles != null) {
      for (InternalFactHandle handle : orderFacts(matchFactHandles)) {
        Object object = handle.getObject();
        handle.setObject(
            null); // we must set it to null as we don't want to write out the Activation
        writeFactHandle(context, stream, objectMarshallingStrategyStore, handle);
        handle.setObject(object); // restore object
        writeRightTuples(handle, context);
      }
    }

    // writeLeftTuples( context );
    writeLeftTuples(context, orderFacts(objectStore));

    if (matchFactHandles != null) {
      stream.writeBoolean(true);
      writeLeftTuples(context, orderFacts(matchFactHandles));
    } else {
      stream.writeBoolean(false);
    }
  }
  /**
   *
   *
   * <pre>
   *
   *
   *                type == &quot;cheddar&quot &amp;&amp; price &gt; 10
   *
   *
   * </pre>
   *
   * Test the use of the composite AND constraint. Composite AND constraints are only used when
   * nested inside other field constraints, as the top level AND is implicit
   *
   * @throws IntrospectionException
   */
  public void testCompositeAndConstraint() {
    final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
    final InternalWorkingMemory workingMemory =
        (InternalWorkingMemory) ruleBase.newStatefulSession();

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

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

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

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

    final ClassFieldExtractor priceExtractor =
        cache.getExtractor(Cheese.class, "price", getClass().getClassLoader());

    final FieldValue priceField = FieldFactory.getFieldValue(10);

    final Evaluator priceEvaluator = ValueType.INTEGER_TYPE.getEvaluator(Operator.GREATER);

    final LiteralConstraint constraint2 =
        new LiteralConstraint(priceExtractor, priceEvaluator, priceField);

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

    final AndConstraint constraint = new AndConstraint();
    constraint.addAlphaConstraint(constraint1);
    constraint.addAlphaConstraint(constraint2);

    final ContextEntry context = constraint.createContextEntry();

    final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert(cheddar);

    // check constraint
    assertTrue(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context));

    cheddar.setPrice(5);
    ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
    assertFalse(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context));

    cheddar.setType("stilton");
    ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
    assertFalse(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context));

    cheddar.setPrice(15);
    ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
    assertFalse(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context));
  }
    public boolean evaluateCachedLeft(
        InternalWorkingMemory workingMemory,
        final VariableContextEntry context,
        final InternalFactHandle right) {
      if (context.leftNull || context.extractor.isNullValue(workingMemory, right.getObject())) {
        return false;
      }

      long distStart =
          ((EventFactHandle) right).getStartTimestamp()
              - ((TemporalVariableContextEntry) context).startTS;
      long distEnd =
          Math.abs(
              ((TemporalVariableContextEntry) context).endTS
                  - ((EventFactHandle) right).getEndTimestamp());
      return this.getOperator().isNegated() ^ (distStart > 0 && distEnd <= this.endDev);
    }
Example #19
0
  public void assertObject(
      final InternalFactHandle handle,
      final PropagationContext context,
      final ObjectTypeConf objectTypeConf,
      final InternalWorkingMemory workingMemory) {
    // checks if shadow is enabled
    if (objectTypeConf.isShadowEnabled()) {
      // the user has implemented the ShadowProxy interface, let their implementation
      // know it is safe to update the information the engine can see.
      ((ShadowProxy) handle.getObject()).updateProxy();
    }

    ObjectTypeNode[] cachedNodes = objectTypeConf.getObjectTypeNodes();

    for (int i = 0, length = cachedNodes.length; i < length; i++) {
      cachedNodes[i].assertObject(handle, context, workingMemory);
    }
  }
Example #20
0
 private void reaccumulateForLeftTuple(
     final LeftTuple leftTuple,
     final InternalWorkingMemory workingMemory,
     final AccumulateMemory memory,
     final AccumulateContext accctx) {
   this.accumulate.init(memory.workingMemoryContext, accctx.context, leftTuple, workingMemory);
   for (LeftTuple childMatch = getFirstMatch(leftTuple, accctx, false);
       childMatch != null;
       childMatch = childMatch.getLeftParentNext()) {
     InternalFactHandle childHandle = childMatch.getRightParent().getFactHandle();
     LeftTuple tuple = leftTuple;
     if (this.unwrapRightObject) {
       tuple = (LeftTuple) childHandle.getObject();
       childHandle = tuple.getLastHandle();
     }
     this.accumulate.accumulate(
         memory.workingMemoryContext, accctx.context, tuple, childHandle, workingMemory);
   }
 }
    /** @inheridDoc */
    public boolean evaluate(
        InternalWorkingMemory workingMemory,
        InternalReadAccessor extractor,
        InternalFactHandle handle,
        FieldValue value) {
      final Object objectValue = extractor.getValue(workingMemory, handle.getObject());
      final Object literal = value.getValue();
      if (cachedValue != literal) {
        cachedValue = literal;
        cacheLiteral(literal, workingMemory);
      }

      TraitableBean core;
      if (objectValue instanceof Thing) {
        Thing thing = (Thing) objectValue;
        core = (TraitableBean) thing.getCore();
        BitSet code = core.getCurrentTypeCode();
        if (code != null) {
          return this.getOperator().isNegated() ^ isA(code, cachedLiteral);
        } else {
          return this.getOperator().isNegated() ^ hasTrait(core, literal);
        }
      } else if (objectValue instanceof TraitableBean) {
        core = (TraitableBean) objectValue;
        BitSet code = core.getCurrentTypeCode();
        if (code != null) {
          return this.getOperator().isNegated() ^ isA(code, cachedLiteral);
        } else {
          return this.getOperator().isNegated() ^ hasTrait(core, literal);
        }
      } else {
        core = lookForWrapper(objectValue, workingMemory);
        if (core == null) {
          return this.getOperator().isNegated();
        }
        BitSet code = core.getCurrentTypeCode();
        if (code != null) {
          return this.getOperator().isNegated() ^ isA(code, cachedLiteral);
        } else {
          return this.getOperator().isNegated() ^ hasTrait(core, literal);
        }
      }
    }
Example #22
0
  /**
   * Retract the <code>FactHandleimpl</code> from the <code>Rete</code> network. Also remove the
   * <code>FactHandleImpl</code> from the node memory.
   *
   * @param rightTuple The fact handle.
   * @param object The object to assert.
   * @param workingMemory The working memory session.
   */
  public void retractObject(
      final InternalFactHandle factHandle,
      final PropagationContext context,
      final InternalWorkingMemory workingMemory) {
    if (objectMemoryEnabled && !(queryNode && !((DroolsQuery) factHandle.getObject()).isOpen())) {
      final ObjectHashSet memory = (ObjectHashSet) workingMemory.getNodeMemory(this);
      memory.remove(factHandle);
    }

    for (RightTuple rightTuple = factHandle.getFirstRightTuple();
        rightTuple != null;
        rightTuple = (RightTuple) rightTuple.getHandleNext()) {
      rightTuple.getRightTupleSink().retractRightTuple(rightTuple, context, workingMemory);
    }
    factHandle.clearRightTuples();

    for (LeftTuple leftTuple = factHandle.getFirstLeftTuple();
        leftTuple != null;
        leftTuple = (LeftTuple) leftTuple.getLeftParentNext()) {
      leftTuple.getLeftTupleSink().retractLeftTuple(leftTuple, context, workingMemory);
    }
    factHandle.clearLeftTuples();
  }
Example #23
0
  public void modifyObject(
      final InternalFactHandle handle,
      final PropagationContext context,
      final ObjectTypeConf objectTypeConf,
      final InternalWorkingMemory workingMemory) {
    // checks if shadow is enabled
    if (objectTypeConf.isShadowEnabled()) {
      // the user has implemented the ShadowProxy interface, let their implementation
      // know it is safe to update the information the engine can see.
      ((ShadowProxy) handle.getObject()).updateProxy();
    }

    ObjectTypeNode[] cachedNodes = objectTypeConf.getObjectTypeNodes();

    // make a reference to the previous tuples, then null then on the handle
    ModifyPreviousTuples modifyPreviousTuples =
        new ModifyPreviousTuples(handle.getFirstLeftTuple(), handle.getFirstRightTuple());
    handle.clearLeftTuples();
    handle.clearRightTuples();

    for (int i = 0, length = cachedNodes.length; i < length; i++) {
      cachedNodes[i].modifyObject(handle, modifyPreviousTuples, context, workingMemory);

      // remove any right tuples that matches the current OTN before continue the modify on the next
      // OTN cache entry
      if (i < cachedNodes.length - 1) {
        RightTuple rightTuple = modifyPreviousTuples.peekRightTuple();
        while (rightTuple != null
            && rightTuple.getRightTupleSink() instanceof BetaNode
            && ((BetaNode) rightTuple.getRightTupleSink()).getObjectTypeNode() == cachedNodes[i]) {
          modifyPreviousTuples.removeRightTuple();
          rightTuple = modifyPreviousTuples.peekRightTuple();
        }
      }
    }
    modifyPreviousTuples.retractTuples(context, workingMemory);
  }
  private static ProtobufMessages.FactHandle writeFactHandle(
      MarshallerWriteContext context,
      ObjectMarshallingStrategyStore objectMarshallingStrategyStore,
      InternalFactHandle handle)
      throws IOException {
    ProtobufMessages.FactHandle.Builder _handle = ProtobufMessages.FactHandle.newBuilder();

    _handle.setType(getHandleType(handle));
    _handle.setId(handle.getId());
    _handle.setRecency(handle.getRecency());

    if (_handle.getType() == ProtobufMessages.FactHandle.HandleType.EVENT) {
      // is event
      EventFactHandle efh = (EventFactHandle) handle;
      _handle.setTimestamp(efh.getStartTimestamp());
      _handle.setDuration(efh.getDuration());
      _handle.setIsExpired(efh.isExpired());
      _handle.setActivationsCount(efh.getActivationsCount());
    }

    Object object = handle.getObject();

    if (object != null) {
      ObjectMarshallingStrategy strategy = objectMarshallingStrategyStore.getStrategyObject(object);

      String strategyClassName = strategy.getClass().getName();
      Integer index = context.usedStrategies.get(strategyClassName);
      if (index == null) {
        index = Integer.valueOf(context.usedStrategies.size());
        context.usedStrategies.put(strategyClassName, index);
      }
      _handle.setStrategyIndex(index.intValue());
      _handle.setObject(ByteString.copyFrom(strategy.marshal(context, object)));
    }

    return _handle.build();
  }
Example #25
0
  public static void writeLeftTuple(
      LeftTuple leftTuple, MarshallerWriteContext context, boolean recurse) throws IOException {
    ObjectOutputStream stream = context.stream;
    InternalRuleBase ruleBase = context.ruleBase;
    InternalWorkingMemory wm = context.wm;

    LeftTupleSink sink = leftTuple.getLeftTupleSink();

    switch (sink.getType()) {
      case NodeTypeEnums.JoinNode:
        {
          // context.out.println( "JoinNode" );
          for (LeftTuple childLeftTuple = leftTuple.getFirstChild();
              childLeftTuple != null;
              childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) {
            stream.writeShort(PersisterEnums.RIGHT_TUPLE);
            int childSinkId = childLeftTuple.getLeftTupleSink().getId();
            stream.writeInt(childSinkId);
            stream.writeInt(childLeftTuple.getRightParent().getFactHandle().getId());
            // context.out.println( "RightTuple int:" + childLeftTuple.getLeftTupleSink().getId() +
            // " int:" + childLeftTuple.getRightParent().getFactHandle().getId() );
            writeLeftTuple(childLeftTuple, context, recurse);
          }
          stream.writeShort(PersisterEnums.END);
          // context.out.println( "JoinNode   ---   END" );
          break;
        }
      case NodeTypeEnums.QueryRiaFixerNode:
      case NodeTypeEnums.EvalConditionNode:
        {
          // context.out.println( ".... EvalConditionNode" );
          for (LeftTuple childLeftTuple = leftTuple.getFirstChild();
              childLeftTuple != null;
              childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) {
            stream.writeShort(PersisterEnums.LEFT_TUPLE);
            stream.writeInt(childLeftTuple.getLeftTupleSink().getId());
            writeLeftTuple(childLeftTuple, context, recurse);
          }
          stream.writeShort(PersisterEnums.END);
          // context.out.println( "---- EvalConditionNode   ---   END" );
          break;
        }
      case NodeTypeEnums.NotNode:
      case NodeTypeEnums.ForallNotNode:
        {
          if (leftTuple.getBlocker() == null) {
            // is not blocked so has children
            stream.writeShort(PersisterEnums.LEFT_TUPLE_NOT_BLOCKED);

            for (LeftTuple childLeftTuple = leftTuple.getFirstChild();
                childLeftTuple != null;
                childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) {
              stream.writeShort(PersisterEnums.LEFT_TUPLE);
              stream.writeInt(childLeftTuple.getLeftTupleSink().getId());
              writeLeftTuple(childLeftTuple, context, recurse);
            }
            stream.writeShort(PersisterEnums.END);

          } else {
            stream.writeShort(PersisterEnums.LEFT_TUPLE_BLOCKED);
            stream.writeInt(leftTuple.getBlocker().getFactHandle().getId());
          }
          break;
        }
      case NodeTypeEnums.ExistsNode:
        {
          if (leftTuple.getBlocker() == null) {
            // is blocked so has children
            stream.writeShort(PersisterEnums.LEFT_TUPLE_NOT_BLOCKED);
          } else {
            stream.writeShort(PersisterEnums.LEFT_TUPLE_BLOCKED);
            stream.writeInt(leftTuple.getBlocker().getFactHandle().getId());

            for (LeftTuple childLeftTuple = leftTuple.getFirstChild();
                childLeftTuple != null;
                childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) {
              stream.writeShort(PersisterEnums.LEFT_TUPLE);
              stream.writeInt(childLeftTuple.getLeftTupleSink().getId());
              writeLeftTuple(childLeftTuple, context, recurse);
            }
            stream.writeShort(PersisterEnums.END);
          }
          break;
        }
      case NodeTypeEnums.AccumulateNode:
        {
          // context.out.println( ".... AccumulateNode" );
          // accumulate nodes generate new facts on-demand and need special procedures when
          // serializing to persistent storage
          AccumulateMemory memory = (AccumulateMemory) context.wm.getNodeMemory((BetaNode) sink);
          AccumulateContext accctx = (AccumulateContext) leftTuple.getObject();
          // first we serialize the generated fact handle
          writeFactHandle(
              context,
              stream,
              context.objectMarshallingStrategyStore,
              accctx.result.getFactHandle());
          // then we serialize the associated accumulation context
          stream.writeObject(accctx.context);
          // then we serialize the boolean propagated flag
          stream.writeBoolean(accctx.propagated);

          // then we serialize all the propagated tuples
          for (LeftTuple childLeftTuple = leftTuple.getFirstChild();
              childLeftTuple != null;
              childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) {
            if (leftTuple.getLeftTupleSink().getId() == childLeftTuple.getLeftTupleSink().getId()) {
              // this is a matching record, so, associate the right tuples
              // context.out.println( "RightTuple(match) int:" +
              // childLeftTuple.getLeftTupleSink().getId() + " int:" +
              // childLeftTuple.getRightParent().getFactHandle().getId() );
              stream.writeShort(PersisterEnums.RIGHT_TUPLE);
              stream.writeInt(childLeftTuple.getRightParent().getFactHandle().getId());
            } else {
              // this is a propagation record
              // context.out.println( "RightTuple(propagation) int:" +
              // childLeftTuple.getLeftTupleSink().getId() + " int:" +
              // childLeftTuple.getRightParent().getFactHandle().getId() );
              stream.writeShort(PersisterEnums.LEFT_TUPLE);
              int sinkId = childLeftTuple.getLeftTupleSink().getId();
              stream.writeInt(sinkId);
              writeLeftTuple(childLeftTuple, context, recurse);
            }
          }
          stream.writeShort(PersisterEnums.END);
          // context.out.println( "---- AccumulateNode   ---   END" );
          break;
        }
      case NodeTypeEnums.RightInputAdaterNode:
        {
          // context.out.println( ".... RightInputAdapterNode" );
          // RIANs generate new fact handles on-demand to wrap tuples and need special procedures
          // when serializing to persistent storage
          ObjectHashMap memory = (ObjectHashMap) context.wm.getNodeMemory((NodeMemory) sink);
          InternalFactHandle ifh = (InternalFactHandle) memory.get(leftTuple);
          // first we serialize the generated fact handle ID
          // context.out.println( "FactHandle id:"+ifh.getId() );
          stream.writeInt(ifh.getId());
          stream.writeLong(ifh.getRecency());

          writeRightTuples(ifh, context);

          stream.writeShort(PersisterEnums.END);
          // context.out.println( "---- RightInputAdapterNode   ---   END" );
          break;
        }
      case NodeTypeEnums.FromNode:
        {
          // context.out.println( ".... FromNode" );
          // FNs generate new fact handles on-demand to wrap objects and need special procedures
          // when serializing to persistent storage
          FromMemory memory = (FromMemory) context.wm.getNodeMemory((NodeMemory) sink);

          Map<Object, RightTuple> matches = (Map<Object, RightTuple>) leftTuple.getObject();
          for (RightTuple rightTuples : matches.values()) {
            // first we serialize the generated fact handle ID
            stream.writeShort(PersisterEnums.FACT_HANDLE);
            writeFactHandle(
                context,
                stream,
                context.objectMarshallingStrategyStore,
                rightTuples.getFactHandle());
            writeRightTuples(rightTuples.getFactHandle(), context);
          }
          stream.writeShort(PersisterEnums.END);
          for (LeftTuple childLeftTuple = leftTuple.getFirstChild();
              childLeftTuple != null;
              childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) {
            stream.writeShort(PersisterEnums.RIGHT_TUPLE);
            stream.writeInt(childLeftTuple.getLeftTupleSink().getId());
            stream.writeInt(childLeftTuple.getRightParent().getFactHandle().getId());
            // context.out.println( "RightTuple int:" + childLeftTuple.getLeftTupleSink().getId() +
            // " int:" + childLeftTuple.getRightParent().getFactHandle().getId() );
            writeLeftTuple(childLeftTuple, context, recurse);
          }
          stream.writeShort(PersisterEnums.END);
          // context.out.println( "---- FromNode   ---   END" );
          break;
        }
      case NodeTypeEnums.UnificationNode:
        {
          // context.out.println( ".... UnificationNode" );

          QueryElementNode node = (QueryElementNode) sink;
          boolean isOpen = node.isOpenQuery();

          context.writeBoolean(isOpen);
          if (isOpen) {
            InternalFactHandle factHandle = (InternalFactHandle) leftTuple.getObject();
            DroolsQuery query = (DroolsQuery) factHandle.getObject();

            // context.out.println( "factHandle:" +  factHandle );

            factHandle.setObject(null);
            writeFactHandle(context, stream, context.objectMarshallingStrategyStore, 0, factHandle);
            factHandle.setObject(query);
            writeLeftTuples(context, new InternalFactHandle[] {factHandle});
          } else {
            for (LeftTuple childLeftTuple = leftTuple.getFirstChild();
                childLeftTuple != null;
                childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) {
              stream.writeShort(PersisterEnums.LEFT_TUPLE);
              stream.writeInt(childLeftTuple.getLeftTupleSink().getId());
              InternalFactHandle factHandle = childLeftTuple.getLastHandle();
              writeFactHandle(
                  context, stream, context.objectMarshallingStrategyStore, 1, factHandle);
              writeLeftTuple(childLeftTuple, context, recurse);
            }
            stream.writeShort(PersisterEnums.END);
          }
          // context.out.println( "---- EvalConditionNode   ---   END" );
          break;
        }
      case NodeTypeEnums.RuleTerminalNode:
        {
          // context.out.println( "RuleTerminalNode" );
          int pos = context.terminalTupleMap.size();
          context.terminalTupleMap.put(leftTuple, pos);
          break;
        }
      case NodeTypeEnums.QueryTerminalNode:
        {
          // context.out.println( ".... QueryTerminalNode" );
          //                LeftTuple entry = leftTuple;
          //
          //                // find the DroolsQuery object
          //                while ( entry.getParent() != null ) {
          //                    entry = entry.getParent();
          //                }
          //
          //                // Now output all the child tuples in the caller network
          //                DroolsQuery query = (DroolsQuery) entry.getLastHandle().getObject();
          //                if ( query.getQueryResultCollector() instanceof
          // UnificationNodeViewChangedEventListener ) {
          //                    context.writeBoolean( true );
          //                    UnificationNodeViewChangedEventListener collector =
          // (UnificationNodeViewChangedEventListener) query.getQueryResultCollector();
          //                    leftTuple = collector.getLeftTuple();
          //
          context.writeBoolean(true);
          RightTuple rightTuple = (RightTuple) leftTuple.getObject();
          // context.out.println( "rightTuple:" +  rightTuple.getFactHandle() );
          writeFactHandle(
              context,
              stream,
              context.objectMarshallingStrategyStore,
              1,
              rightTuple.getFactHandle());

          for (LeftTuple childLeftTuple = rightTuple.firstChild;
              childLeftTuple != null;
              childLeftTuple = (LeftTuple) childLeftTuple.getRightParentNext()) {
            stream.writeShort(PersisterEnums.LEFT_TUPLE);
            stream.writeInt(childLeftTuple.getLeftTupleSink().getId());
            writeLeftTuple(childLeftTuple, context, recurse);
          }

          //                    for ( LeftTuple childLeftTuple = leftTuple.getFirstChild();
          // childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()
          // ) {
          //                        stream.writeShort( PersisterEnums.LEFT_TUPLE );
          //                        stream.writeInt( childLeftTuple.getLeftTupleSink().getId() );
          //                        writeFactHandle( context,
          //                                         stream,
          //                                         context.objectMarshallingStrategyStore,
          //                                         1,
          //                                         childLeftTuple.getLastHandle() );
          //                        writeLeftTuple( childLeftTuple,
          //                                        context,
          //                                        recurse );
          //                    }
          //                } else {
          //                    context.writeBoolean( false );
          //                }
          stream.writeShort(PersisterEnums.END);
          // context.out.println( "---- QueryTerminalNode   ---   END" );
          break;
        }
    }
  }
  public static Activation readActivation(MarshallerReaderContext context) throws IOException {
    ObjectInputStream stream = context.stream;
    InternalRuleBase ruleBase = context.ruleBase;
    InternalWorkingMemory wm = context.wm;

    long activationNumber = stream.readLong();

    int pos = stream.readInt();
    LeftTuple leftTuple = context.terminalTupleMap.get(pos);

    int salience = stream.readInt();

    String pkgName = stream.readUTF();
    String ruleName = stream.readUTF();
    Package pkg = ruleBase.getPackage(pkgName);
    Rule rule = pkg.getRule(ruleName);

    RuleTerminalNode ruleTerminalNode = (RuleTerminalNode) leftTuple.getLeftTupleSink();

    PropagationContext pc = context.propagationContexts.get(stream.readLong());

    AgendaItem activation;

    boolean scheduled = false;
    if (rule.getTimer() != null) {
      activation =
          new ScheduledAgendaItem(
              activationNumber, leftTuple, (InternalAgenda) wm.getAgenda(), pc, ruleTerminalNode);
      scheduled = true;
    } else {
      activation = new AgendaItem(activationNumber, leftTuple, salience, pc, ruleTerminalNode);
    }
    leftTuple.setObject(activation);

    if (stream.readBoolean()) {
      String activationGroupName = stream.readUTF();
      ((DefaultAgenda) wm.getAgenda())
          .getActivationGroup(activationGroupName)
          .addActivation(activation);
    }

    boolean activated = stream.readBoolean();
    activation.setActivated(activated);

    if (stream.readBoolean()) {
      InternalFactHandle handle = context.handles.get(stream.readInt());
      activation.setFactHandle(handle);
      handle.setObject(activation);
    }

    InternalAgendaGroup agendaGroup;
    if (rule.getAgendaGroup() == null
        || rule.getAgendaGroup().equals("")
        || rule.getAgendaGroup().equals(AgendaGroup.MAIN)) {
      // Is the Rule AgendaGroup undefined? If it is use MAIN,
      // which is added to the Agenda by default
      agendaGroup =
          (InternalAgendaGroup) ((DefaultAgenda) wm.getAgenda()).getAgendaGroup(AgendaGroup.MAIN);
    } else {
      // AgendaGroup is defined, so try and get the AgendaGroup
      // from the Agenda
      agendaGroup =
          (InternalAgendaGroup)
              ((DefaultAgenda) wm.getAgenda()).getAgendaGroup(rule.getAgendaGroup());
    }

    activation.setAgendaGroup(agendaGroup);

    if (!scheduled && activated) {
      if (rule.getRuleFlowGroup() == null) {
        agendaGroup.add(activation);
      } else {
        InternalRuleFlowGroup rfg =
            (InternalRuleFlowGroup)
                ((DefaultAgenda) wm.getAgenda()).getRuleFlowGroup(rule.getRuleFlowGroup());
        rfg.addActivation(activation);
      }
    }

    TruthMaintenanceSystem tms = context.wm.getTruthMaintenanceSystem();
    while (stream.readShort() == PersisterEnums.LOGICAL_DEPENDENCY) {
      int factHandleId = stream.readInt();
      InternalFactHandle handle = (InternalFactHandle) context.handles.get(factHandleId);
      ObjectTypeConf typeConf =
          context
              .wm
              .getObjectTypeConfigurationRegistry()
              .getObjectTypeConf(
                  ((NamedEntryPoint) handle.getEntryPoint()).getEntryPoint(), handle.getObject());
      tms.addLogicalDependency(handle, activation, pc, rule, typeConf);
    }

    return activation;
  }
Example #27
0
  public void modifyLeftTuple(
      LeftTuple leftTuple, PropagationContext context, InternalWorkingMemory workingMemory) {
    boolean executeAsOpenQuery = openQuery;
    if (executeAsOpenQuery) {
      // There is no point in doing an open query if the caller is a non-open query.
      Object object = ((InternalFactHandle) leftTuple.get(0)).getObject();
      if (object instanceof DroolsQuery && !((DroolsQuery) object).isOpen()) {
        executeAsOpenQuery = false;
      }
    }

    if (!executeAsOpenQuery) {
      // Was never open so execute as a retract + assert
      if (leftTuple.getFirstChild() != null) {
        this.sink.propagateRetractLeftTuple(leftTuple, context, workingMemory);
      }
      assertLeftTuple(leftTuple, context, workingMemory);
      return;
    }

    InternalFactHandle handle = (InternalFactHandle) leftTuple.getObject();
    DroolsQuery queryObject = (DroolsQuery) handle.getObject();
    if (queryObject.getAction() != null) {
      // we already have an insert scheduled for this query, but have re-entered it
      // do nothing
      return;
    }

    Object[] argTemplate =
        this.queryElement.getArgTemplate(); // an array of declr, variable and literals
    Object[] args =
        new Object[argTemplate.length]; // the actual args, to be created from the  template

    // first copy everything, so that we get the literals. We will rewrite the declarations and
    // variables next
    System.arraycopy(argTemplate, 0, args, 0, args.length);

    int[] declIndexes = this.queryElement.getDeclIndexes();

    for (int i = 0, length = declIndexes.length; i < length; i++) {
      Declaration declr = (Declaration) argTemplate[declIndexes[i]];

      Object tupleObject = leftTuple.get(declr).getObject();

      Object o;

      if (tupleObject instanceof DroolsQuery) {
        // If the query passed in a Variable, we need to use it
        ArrayElementReader arrayReader = (ArrayElementReader) declr.getExtractor();
        if (((DroolsQuery) tupleObject).getVariables()[arrayReader.getIndex()] != null) {
          o = Variable.v;
        } else {
          o = declr.getValue(workingMemory, tupleObject);
        }
      } else {
        o = declr.getValue(workingMemory, tupleObject);
      }

      args[declIndexes[i]] = o;
    }

    int[] varIndexes = this.queryElement.getVariableIndexes();
    for (int i = 0, length = varIndexes.length; i < length; i++) {
      if (argTemplate[varIndexes[i]] == Variable.v) {
        // Need to check against the arg template, as the varIndexes also includes re-declared
        // declarations
        args[varIndexes[i]] = Variable.v;
      }
    }

    queryObject.setParameters(args);
    ((UnificationNodeViewChangedEventListener) queryObject.getQueryResultCollector())
        .setVariables(varIndexes);

    QueryUpdateAction action = new QueryUpdateAction(context, handle, leftTuple, this);
    context.getQueue1().addFirst(action);
  }
  /**
   *
   *
   * <pre>
   *
   *
   *                (Cheese (price ?price1 )
   *                (Cheese (price ?price2&amp;:(= ?price2 (* 2 ?price1) )
   *
   *
   * </pre>
   *
   * @throws IntrospectionException
   */
  public void testPredicateConstraint() throws IntrospectionException {
    final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
    final InternalWorkingMemory workingMemory =
        (InternalWorkingMemory) ruleBase.newStatefulSession();

    final FieldExtractor priceExtractor =
        cache.getExtractor(Cheese.class, "price", getClass().getClassLoader());

    Pattern pattern = new Pattern(0, new ClassObjectType(Cheese.class));

    // Bind the extractor to a decleration
    // Declarations know the pattern they derive their value form
    final Declaration price1Declaration = new Declaration("price1", priceExtractor, pattern);

    pattern = new Pattern(1, new ClassObjectType(Cheese.class));

    // Bind the extractor to a decleration
    // Declarations know the pattern they derive their value form
    final Declaration price2Declaration = new Declaration("price2", priceExtractor, pattern);

    final PredicateExpression evaluator =
        new PredicateExpression() {

          /** */
          private static final long serialVersionUID = 400L;

          public boolean evaluate(
              Object object,
              Tuple tuple,
              Declaration[] previousDeclarations,
              Declaration[] localDeclarations,
              WorkingMemory workingMemory,
              Object context) {
            int price1 =
                previousDeclarations[0].getIntValue(
                    (InternalWorkingMemory) workingMemory,
                    workingMemory.getObject(tuple.get(previousDeclarations[0])));
            int price2 =
                localDeclarations[0].getIntValue((InternalWorkingMemory) workingMemory, object);

            return (price2 == (price1 * 2));
          }

          public Object createContext() {
            return null;
          }
        };

    final PredicateConstraint constraint1 =
        new PredicateConstraint(
            evaluator,
            new Declaration[] {price1Declaration},
            new Declaration[] {price2Declaration},
            new String[] {});

    final Cheese cheddar0 = new Cheese("cheddar", 5);
    final FactHandle f0 = workingMemory.insert(cheddar0);
    InstrumentedReteTuple tuple = new InstrumentedReteTuple(f0);

    final Cheese cheddar1 = new Cheese("cheddar", 10);
    final InternalFactHandle f1 = (InternalFactHandle) workingMemory.insert(cheddar1);

    tuple = new InstrumentedReteTuple(tuple, f1);

    final PredicateContextEntry context = (PredicateContextEntry) constraint1.createContextEntry();
    context.updateFromTuple(workingMemory, tuple);
    assertTrue(constraint1.isAllowedCachedLeft(context, f1.getObject()));
  }
  /**
   *
   *
   * <pre>
   *
   *
   *                Cheese( ( type == &quot;cheddar&quot &amp;&amp; price &gt; 10) || ( type == &quote;stilton&quote; && price &lt; 10 ) )
   *
   *
   * </pre>
   *
   * Test the use of the composite OR constraint.
   *
   * @throws IntrospectionException
   */
  public void testNestedCompositeConstraints() {
    final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
    final InternalWorkingMemory workingMemory =
        (InternalWorkingMemory) ruleBase.newStatefulSession();

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

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

    final Evaluator stringEqual = ValueType.STRING_TYPE.getEvaluator(Operator.EQUAL);

    // type == 'cheddar'
    final LiteralConstraint constraint1 =
        new LiteralConstraint(typeExtractor, stringEqual, cheddarField);

    final ClassFieldExtractor priceExtractor =
        cache.getExtractor(Cheese.class, "price", getClass().getClassLoader());

    final FieldValue field10 = FieldFactory.getFieldValue(10);

    final Evaluator integerGreater = ValueType.INTEGER_TYPE.getEvaluator(Operator.GREATER);

    // price > 10
    final LiteralConstraint constraint2 =
        new LiteralConstraint(priceExtractor, integerGreater, field10);

    // type == 'cheddar' && price > 10
    final AndConstraint and1 = new AndConstraint();
    and1.addAlphaConstraint(constraint1);
    and1.addAlphaConstraint(constraint2);

    final FieldValue stiltonField = FieldFactory.getFieldValue("stilton");
    // type == 'stilton'
    final LiteralConstraint constraint3 =
        new LiteralConstraint(typeExtractor, stringEqual, stiltonField);

    final Evaluator integerLess = ValueType.INTEGER_TYPE.getEvaluator(Operator.LESS);

    // price < 10
    final LiteralConstraint constraint4 =
        new LiteralConstraint(priceExtractor, integerLess, field10);

    // type == 'stilton' && price < 10
    final AndConstraint and2 = new AndConstraint();
    and2.addAlphaConstraint(constraint3);
    and2.addAlphaConstraint(constraint4);

    // ( type == 'cheddar' && price > 10 ) || ( type == 'stilton' && price < 10 )
    final OrConstraint constraint = new OrConstraint();
    constraint.addAlphaConstraint(and1);
    constraint.addAlphaConstraint(and2);
    final ContextEntry context = constraint.createContextEntry();

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

    final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert(cheddar);

    // check constraint
    assertTrue(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context));

    cheddar.setPrice(5);
    ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
    assertFalse(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context));

    cheddar.setType("stilton");
    ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
    assertTrue(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context));

    cheddar.setPrice(15);
    ((ShadowProxy) cheddarHandle.getObject()).updateProxy();
    assertFalse(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context));
  }
  /**
   *
   *
   * <pre>
   *
   *
   *                (Cheese (price ?price )
   *                (Cheese (price =(* 2 ?price) )
   *                (Cheese (price &gt;(* 2 ?price) )
   *
   *
   * </pre>
   *
   * @throws IntrospectionException
   */
  public void testReturnValueConstraint() throws IntrospectionException {
    final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase();
    final InternalWorkingMemory workingMemory =
        (InternalWorkingMemory) ruleBase.newStatefulSession();

    final FieldExtractor priceExtractor =
        cache.getExtractor(Cheese.class, "price", getClass().getClassLoader());

    final Pattern pattern = new Pattern(0, new ClassObjectType(Cheese.class));

    // Bind the extractor to a decleration
    // Declarations know the pattern they derive their value form
    final Declaration priceDeclaration = new Declaration("price1", priceExtractor, pattern);

    final ReturnValueExpression isDoubleThePrice =
        new ReturnValueExpression() {
          /** */
          private static final long serialVersionUID = 400L;

          public FieldValue evaluate(
              Object object,
              Tuple tuple, // ?price
              Declaration[] previousDeclarations,
              Declaration[] localDeclarations,
              WorkingMemory workingMemory,
              Object context) {
            int price =
                ((Number)
                        previousDeclarations[0].getValue(
                            (InternalWorkingMemory) workingMemory,
                            workingMemory.getObject(tuple.get(previousDeclarations[0]))))
                    .intValue();
            return FieldFactory.getFieldValue(2 * price);
          }

          public Object createContext() {
            return null;
          }
        };

    final ReturnValueRestriction restriction1 =
        new ReturnValueRestriction(
            priceExtractor,
            isDoubleThePrice,
            new Declaration[] {priceDeclaration},
            new Declaration[0],
            new String[0],
            ValueType.INTEGER_TYPE.getEvaluator(Operator.EQUAL));

    final ReturnValueConstraint constraint1 =
        new ReturnValueConstraint(priceExtractor, restriction1);

    final ReturnValueRestriction restriction2 =
        new ReturnValueRestriction(
            priceExtractor,
            isDoubleThePrice,
            new Declaration[] {priceDeclaration},
            new Declaration[0],
            new String[0],
            ValueType.INTEGER_TYPE.getEvaluator(Operator.GREATER));

    final ReturnValueConstraint constraint2 =
        new ReturnValueConstraint(priceExtractor, restriction2);

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

    InstrumentedReteTuple tuple = new InstrumentedReteTuple(f0);

    final Cheese cheddar1 = new Cheese("cheddar", 10);
    final InternalFactHandle f1 = (InternalFactHandle) workingMemory.insert(cheddar1);
    tuple = new InstrumentedReteTuple(tuple, f1);

    final ReturnValueContextEntry context1 =
        (ReturnValueContextEntry) constraint1.createContextEntry();
    context1.updateFromTuple(workingMemory, tuple);
    assertTrue(constraint1.isAllowedCachedLeft(context1, f1.getObject()));

    final ReturnValueContextEntry context2 =
        (ReturnValueContextEntry) constraint2.createContextEntry();
    context2.updateFromTuple(workingMemory, tuple);
    assertFalse(constraint2.isAllowedCachedLeft(context2, f1.getObject()));

    final Cheese cheddar2 = new Cheese("cheddar", 11);

    final InternalFactHandle f2 = (InternalFactHandle) workingMemory.insert(cheddar2);

    assertTrue(constraint2.isAllowedCachedLeft(context2, f2.getObject()));
  }