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);
    }
Exemple #2
0
  /**
   * @inheritDoc As the accumulate node will always generate a resulting tuple, we must always
   *     destroy it
   */
  public void retractLeftTuple(
      final LeftTuple leftTuple,
      final PropagationContext context,
      final InternalWorkingMemory workingMemory) {
    final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory(this);

    if (leftTuple.getMemory().isStagingMemory()) {
      leftTuple.getMemory().remove(leftTuple);
    } else {
      ((BetaMemory) memory.getBetaMemory()).getLeftTupleMemory().remove(leftTuple);
    }
    leftTuple.setMemory(null);

    final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject();
    if (accctx.getAction() != null) {
      // there is a scheduled activation, we must cancel it
      context.removeInsertAction(accctx.getAction());
    }
    leftTuple.setObject(null);

    removePreviousMatchesForLeftTuple(leftTuple, workingMemory, memory, accctx);

    if (accctx.propagated) {
      // if tuple was previously propagated, retract it and destroy result fact handle
      this.sink.propagateRetractLeftTupleDestroyRightTuple(leftTuple, context, workingMemory);
    } else {
      // if not propagated, just destroy the result fact handle
      // workingMemory.getFactHandleFactory().destroyFactHandle( accctx.result.getFactHandle() );
    }
  }
Exemple #3
0
  /**
   * @inheritDoc When a new tuple is asserted into an AccumulateNode, do this:
   *     <p>1. Select all matching objects from right memory 2. Execute the initialization code
   *     using the tuple + matching objects 3. Execute the accumulation code for each combination of
   *     tuple+object 4. Execute the return code 5. Create a new CalculatedObjectHandle for the
   *     resulting object and add it to the tuple 6. Propagate the tuple
   *     <p>The initialization, accumulation and return codes, in JBRules, are assembled into a
   *     generated method code and called once for the whole match, as you can see below:
   *     <p>Object result = this.accumulator.accumulate( ... );
   */
  public void assertLeftTuple(
      final LeftTuple leftTuple,
      final PropagationContext context,
      final InternalWorkingMemory workingMemory) {

    final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory(this);

    AccumulateContext accresult = new AccumulateContext();

    boolean useLeftMemory = true;
    if (!this.tupleMemoryEnabled) {
      // This is a hack, to not add closed DroolsQuery objects
      Object object = ((InternalFactHandle) leftTuple.get(0)).getObject();
      if (!(object instanceof DroolsQuery) || !((DroolsQuery) object).isOpen()) {
        useLeftMemory = false;
      }
    }

    if (useLeftMemory) {
      memory.betaMemory.getLeftTupleMemory().add(leftTuple);
      leftTuple.setObject(accresult);
    }

    accresult.context = this.accumulate.createContext();

    this.accumulate.init(memory.workingMemoryContext, accresult.context, leftTuple, workingMemory);

    this.constraints.updateFromTuple(memory.betaMemory.getContext(), workingMemory, leftTuple);
    RightTupleMemory rightMemory = memory.betaMemory.getRightTupleMemory();

    FastIterator rightIt = getRightIterator(rightMemory);

    for (RightTuple rightTuple = getFirstRightTuple(leftTuple, rightMemory, context, rightIt);
        rightTuple != null;
        rightTuple = (RightTuple) rightIt.next(rightTuple)) {
      InternalFactHandle handle = rightTuple.getFactHandle();
      if (this.constraints.isAllowedCachedLeft(memory.betaMemory.getContext(), handle)) {

        // add a match
        addMatch(
            leftTuple, rightTuple, null, null, workingMemory, memory, accresult, useLeftMemory);
      }
    }

    this.constraints.resetTuple(memory.betaMemory.getContext());

    if (accresult.getAction() == null) {
      evaluateResultConstraints(
          ActivitySource.LEFT, leftTuple, context, workingMemory, memory, accresult, useLeftMemory);
    } // else evaluation is already scheduled, so do nothing
  }
    public void rowAdded(
        final Rule rule,
        LeftTuple resultLeftTuple,
        PropagationContext context,
        InternalWorkingMemory workingMemory) {

      QueryTerminalNode node = (QueryTerminalNode) resultLeftTuple.getLeftTupleSink();
      Declaration[] decls = node.getDeclarations();
      DroolsQuery query = (DroolsQuery) this.factHandle.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 resultHandle =
          createQueryResultHandle(context, workingMemory, objects);

      RightTuple rightTuple = new RightTuple(resultHandle);
      if (query.isOpen()) {
        rightTuple.setLeftTuple(resultLeftTuple);
        resultLeftTuple.setObject(rightTuple);
      }

      this.node
          .getSinkPropagator()
          .createChildLeftTuplesforQuery(
              this.leftTuple,
              rightTuple,
              true, // this must always be true, otherwise we can't
              // find the child tuples to iterate for evaluating the query results
              query.isOpen());

      RightTupleList rightTuples = query.getResultInsertRightTupleList();
      if (rightTuples == null) {
        rightTuples = new RightTupleList();
        query.setResultInsertRightTupleList(rightTuples);
        QueryResultInsertAction evalAction =
            new QueryResultInsertAction(context, this.factHandle, leftTuple, this.node);
        context.getQueue2().addFirst(evalAction);
      }

      rightTuples.add(rightTuple);
    }
    public void rowRemoved(
        final Rule rule,
        final LeftTuple resultLeftTuple,
        final PropagationContext context,
        final InternalWorkingMemory workingMemory) {
      RightTuple rightTuple = (RightTuple) resultLeftTuple.getObject();
      rightTuple.setLeftTuple(null);
      resultLeftTuple.setObject(null);

      DroolsQuery query = (DroolsQuery) this.factHandle.getObject();

      RightTupleList rightTuples = query.getResultRetractRightTupleList();
      if (rightTuples == null) {
        rightTuples = new RightTupleList();
        query.setResultRetractRightTupleList(rightTuples);
        QueryResultRetractAction retractAction =
            new QueryResultRetractAction(context, this.factHandle, leftTuple, this.node);
        context.getQueue2().addFirst(retractAction);
      }
      if (rightTuple.getMemory() != null) {
        throw new RuntimeException();
      }
      rightTuples.add(rightTuple);
    }
  public DroolsQuery createDroolsQuery(
      LeftTuple leftTuple, InternalFactHandle handle, InternalWorkingMemory workingMemory) {
    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;
      }
    }

    UnificationNodeViewChangedEventListener collector =
        new UnificationNodeViewChangedEventListener(
            leftTuple, varIndexes, this, this.tupleMemoryEnabled);

    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;
      }
    }

    DroolsQuery queryObject =
        new DroolsQuery(this.queryElement.getQueryName(), args, collector, executeAsOpenQuery);

    collector.setFactHandle(handle);

    handle.setObject(queryObject);

    leftTuple.setObject(handle); // so it can be retracted later and destroyed

    return queryObject;
  }
  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;
  }
  public static void readLeftTuple(LeftTuple parentLeftTuple, MarshallerReaderContext context)
      throws IOException, ClassNotFoundException {
    ObjectInputStream stream = context.stream;
    Map<Integer, BaseNode> sinks = context.sinks;

    LeftTupleSink sink = parentLeftTuple.getLeftTupleSink();

    switch (sink.getType()) {
      case NodeTypeEnums.JoinNode:
        {
          BetaMemory memory = (BetaMemory) context.wm.getNodeMemory((BetaNode) sink);
          addToLeftMemory(parentLeftTuple, memory);

          while (stream.readShort() == PersisterEnums.RIGHT_TUPLE) {
            int childSinkId = stream.readInt();
            LeftTupleSink childSink = (LeftTupleSink) sinks.get(childSinkId);
            int factHandleId = stream.readInt();
            RightTupleKey key = new RightTupleKey(factHandleId, sink);
            RightTuple rightTuple = context.rightTuples.get(key);
            LeftTuple childLeftTuple =
                childSink.createLeftTuple(parentLeftTuple, rightTuple, null, null, childSink, true);
            readLeftTuple(childLeftTuple, context);
          }
          break;
        }
      case NodeTypeEnums.EvalConditionNode:
        {
          while (stream.readShort() == PersisterEnums.LEFT_TUPLE) {
            LeftTupleSink childSink = (LeftTupleSink) sinks.get(stream.readInt());
            LeftTuple childLeftTuple = childSink.createLeftTuple(parentLeftTuple, childSink, true);
            readLeftTuple(childLeftTuple, context);
          }
          break;
        }
      case NodeTypeEnums.NotNode:
      case NodeTypeEnums.ForallNotNode:
        {
          BetaMemory memory = (BetaMemory) context.wm.getNodeMemory((BetaNode) sink);
          int type = stream.readShort();
          if (type == PersisterEnums.LEFT_TUPLE_NOT_BLOCKED) {
            addToLeftMemory(parentLeftTuple, memory);

            while (stream.readShort() == PersisterEnums.LEFT_TUPLE) {
              LeftTupleSink childSink = (LeftTupleSink) sinks.get(stream.readInt());
              LeftTuple childLeftTuple =
                  childSink.createLeftTuple(parentLeftTuple, childSink, true);
              readLeftTuple(childLeftTuple, context);
            }

          } else {
            int factHandleId = stream.readInt();
            RightTupleKey key = new RightTupleKey(factHandleId, sink);
            RightTuple rightTuple = context.rightTuples.get(key);

            parentLeftTuple.setBlocker(rightTuple);
            rightTuple.addBlocked(parentLeftTuple);
          }
          break;
        }
      case NodeTypeEnums.ExistsNode:
        {
          BetaMemory memory = (BetaMemory) context.wm.getNodeMemory((BetaNode) sink);
          int type = stream.readShort();
          if (type == PersisterEnums.LEFT_TUPLE_NOT_BLOCKED) {
            addToLeftMemory(parentLeftTuple, memory);
          } else {
            int factHandleId = stream.readInt();
            RightTupleKey key = new RightTupleKey(factHandleId, sink);
            RightTuple rightTuple = context.rightTuples.get(key);

            parentLeftTuple.setBlocker(rightTuple);
            rightTuple.addBlocked(parentLeftTuple);

            while (stream.readShort() == PersisterEnums.LEFT_TUPLE) {
              LeftTupleSink childSink = (LeftTupleSink) sinks.get(stream.readInt());
              LeftTuple childLeftTuple =
                  childSink.createLeftTuple(parentLeftTuple, childSink, true);
              readLeftTuple(childLeftTuple, context);
            }
          }
          break;
        }
      case NodeTypeEnums.AccumulateNode:
        {
          // accumulate nodes generate new facts on-demand and need special procedures when
          // de-serializing from persistent storage
          AccumulateMemory memory = (AccumulateMemory) context.wm.getNodeMemory((BetaNode) sink);
          memory.betaMemory.getLeftTupleMemory().add(parentLeftTuple);

          AccumulateContext accctx = new AccumulateContext();
          parentLeftTuple.setObject(accctx);

          // first we de-serialize the generated fact handle
          InternalFactHandle handle = readFactHandle(context);
          accctx.result = new RightTuple(handle, (RightTupleSink) sink);

          // then we de-serialize the associated accumulation context
          accctx.context = (Serializable[]) stream.readObject();
          // then we de-serialize the boolean propagated flag
          accctx.propagated = stream.readBoolean();

          // then we de-serialize all the propagated tuples
          short head = -1;
          while ((head = stream.readShort()) != PersisterEnums.END) {
            switch (head) {
              case PersisterEnums.RIGHT_TUPLE:
                {
                  int factHandleId = stream.readInt();
                  RightTupleKey key = new RightTupleKey(factHandleId, sink);
                  RightTuple rightTuple = context.rightTuples.get(key);
                  // just wiring up the match record
                  sink.createLeftTuple(parentLeftTuple, rightTuple, null, null, sink, true);
                  break;
                }
              case PersisterEnums.LEFT_TUPLE:
                {
                  int sinkId = stream.readInt();
                  LeftTupleSink childSink = (LeftTupleSink) sinks.get(sinkId);
                  LeftTuple childLeftTuple =
                      new LeftTupleImpl(parentLeftTuple, accctx.result, childSink, true);
                  readLeftTuple(childLeftTuple, context);
                  break;
                }
              default:
                {
                  throw new RuntimeDroolsException(
                      "Marshalling error. This is a bug. Please contact the development team.");
                }
            }
          }
          break;
        }
      case NodeTypeEnums.RightInputAdaterNode:
        {
          // RIANs generate new fact handles on-demand to wrap tuples and need special procedures
          // when de-serializing from persistent storage
          ObjectHashMap memory = (ObjectHashMap) context.wm.getNodeMemory((NodeMemory) sink);
          // create fact handle
          int id = stream.readInt();
          long recency = stream.readLong();
          InternalFactHandle handle =
              new DefaultFactHandle(
                  id,
                  parentLeftTuple,
                  recency,
                  context.wm.getEntryPoints().get(EntryPoint.DEFAULT.getEntryPointId()));
          memory.put(parentLeftTuple, handle);

          readRightTuples(handle, context);

          stream.readShort(); // Persistence.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);

          memory.betaMemory.getLeftTupleMemory().add(parentLeftTuple);
          Map<Object, RightTuple> matches = new LinkedHashMap<Object, RightTuple>();
          parentLeftTuple.setObject(matches);

          while (stream.readShort() == PersisterEnums.FACT_HANDLE) {
            // we de-serialize the generated fact handle ID
            InternalFactHandle handle = readFactHandle(context);
            context.handles.put(handle.getId(), handle);
            readRightTuples(handle, context);
            matches.put(handle.getObject(), handle.getFirstRightTuple());
          }
          while (stream.readShort() == PersisterEnums.RIGHT_TUPLE) {
            LeftTupleSink childSink = (LeftTupleSink) sinks.get(stream.readInt());
            int factHandleId = stream.readInt();
            RightTupleKey key =
                new RightTupleKey(
                    factHandleId, null); // created tuples in from node always use null sink
            RightTuple rightTuple = context.rightTuples.get(key);
            LeftTuple childLeftTuple =
                new LeftTupleImpl(parentLeftTuple, rightTuple, childSink, true);
            readLeftTuple(childLeftTuple, context);
          }
          //                context.out.println( "FromNode   ---   END" );
          break;
        }
      case NodeTypeEnums.UnificationNode:
        {
          boolean isOpen = context.readBoolean();

          if (isOpen) {
            QueryElementNode node = (QueryElementNode) sink;
            InternalFactHandle handle = readFactHandle(context);
            context.handles.put(handle.getId(), handle);
            node.createDroolsQuery(parentLeftTuple, handle, context.wm);
            readLeftTuples(context);
          } else {
            while (stream.readShort() == PersisterEnums.LEFT_TUPLE) {
              LeftTupleSink childSink = (LeftTupleSink) sinks.get(stream.readInt());
              // we de-serialize the generated fact handle ID
              InternalFactHandle handle = readFactHandle(context);
              context.handles.put(handle.getId(), handle);
              RightTuple rightTuple = new RightTuple(handle);
              // @TODO check if open query
              LeftTuple childLeftTuple =
                  new LeftTupleImpl(parentLeftTuple, rightTuple, childSink, true);
              readLeftTuple(childLeftTuple, context);
            }
          }
          break;
        }
      case NodeTypeEnums.RuleTerminalNode:
        {
          int pos = context.terminalTupleMap.size();
          context.terminalTupleMap.put(pos, parentLeftTuple);
          break;
        }
      case NodeTypeEnums.QueryTerminalNode:
        {
          boolean unificationNode = context.readBoolean();
          if (unificationNode) {
            // we de-serialize the generated fact handle ID
            InternalFactHandle handle = readFactHandle(context);
            context.handles.put(handle.getId(), handle);
            RightTuple rightTuple = new RightTuple(handle);
            parentLeftTuple.setObject(rightTuple);

            LeftTuple entry = parentLeftTuple;

            // find the DroolsQuery object
            while (entry.getParent() != null) {
              entry = entry.getParent();
            }
            DroolsQuery query = (DroolsQuery) entry.getLastHandle().getObject();
            LeftTuple leftTuple =
                ((UnificationNodeViewChangedEventListener) query.getQueryResultCollector())
                    .getLeftTuple();

            while (stream.readShort() == PersisterEnums.LEFT_TUPLE) {
              LeftTupleSink childSink = (LeftTupleSink) sinks.get(stream.readInt());
              // @TODO check if open query!!!
              LeftTuple childLeftTuple =
                  childSink.createLeftTuple(leftTuple, rightTuple, childSink);
              readLeftTuple(childLeftTuple, context);
            }
          }
          break;
        }
    }
  }