Example #1
0
  /**
   * Do the business of this node. The 2-input nodes, on receiving a token, have to do several
   * things, and their actions change based on whether it's an ADD or REMOVE, and whether it's the
   * right or left input!
   *
   * <PRE>
   *
   * ********** For ADDs, left input:
   * 1) Look for this token in the left memory. If it's there, do nothing;
   * If it's not, add it to the left memory.
   *
   * 2) Perform all this node's tests on this token and each of the right-
   * memory tokens. For any right token for which they succeed:
   *
   * 3) a) append the right token to a copy of this token. b) do a
   * CallNode on each of the successors using this new token.
   *
   * ********** For ADDs, right input:
   *
   * 1) Look for this token in the right memory. If it's there, do nothing;
   * If it's not, add it to the right memory.
   *
   * 2) Perform all this node's tests on this token and each of the left-
   * memory tokens. For any left token for which they succeed:
   *
   * 3) a) append this  token to a copy of the left token. b) do a
   * CallNode on each of the successors using this new token.
   *
   * ********** For REMOVEs, left input:
   *
   * 1) Look for this token in the left memory. If it's there, remove it;
   * else do nothing.
   *
   * 2) Perform all this node's tests on this token and each of the right-
   * memory tokens. For any right token for which they succeed:
   *
   * 3) a) append the right token to a copy of this token. b) do a
   * CallNode on each of the successors using this new token.
   *
   * ********** For REMOVEs, right input:
   *
   * 1) Look for this token in the right memory. If it's there, remove it;
   * else do nothing.
   *
   * 2) Perform all this node's tests on this token and each of the left-
   * memory tokens. For any left token for which they succeed:
   *
   * 3) a) append this token to a copy of the left token. b) do a
   * CallNode on each of the successors using this new token.
   *
   * </PRE>
   */
  boolean CallNode(Token token, int callType) throws ReteException {
    // the four cases listed above are implemented in order.

    // debugPrint(token, callType);
    Token tmp;
    switch (callType) {
      case Node.LEFT:
        switch (token.tag) {
          case RU.ADD:
          case RU.UPDATE:
            if ((tmp = findInMemory(left, token)) == null) left.addElement(token);

            runTestsVaryRight(token);
            break;

          case RU.REMOVE:
            if ((tmp = findInMemory(left, token)) != null) left.removeElement(tmp);

            runTestsVaryRight(token);
            break;

          default:
            throw new ReteException(
                "Node2::CallNode", "Bad tag in token", String.valueOf(token.tag));
        } // switch token.tag
        break; // case Node.LEFT;

      case Node.RIGHT:
        switch (token.tag) {
          case RU.UPDATE:
          case RU.ADD:
            if ((tmp = findInMemory(right, token)) == null) right.addElement(token);

            runTestsVaryLeft(token);
            break;

          case RU.REMOVE:
            if ((tmp = findInMemory(right, token)) != null) right.removeElement(tmp);

            runTestsVaryLeft(token);
            break;

          default:
            throw new ReteException(
                "Node2::CallNode", "Bad tag in token", String.valueOf(token.tag));
        } // switch token.tag
        break; // case Node.RIGHT

      default:
        throw new ReteException("Node2::CallNode", "Bad callType", String.valueOf(callType));
    } // switch callType

    // the runTestsVary* routines pass messages on to the successors.

    return true;
  }
Example #2
0
 /**
  * The system was designed so that right-input tokens have only one fact in them. Furthermore,
  * they'll all have the same class type! As an optimization, then, we could skip the size check
  * and class comparison. For now, I'm leaving it in, using a general comparison function in the
  * Token class. In addition, we're assuming a token can only appear once; this is also by design,
  * and should always be true, unless we implement fact duplication, which CLIPS has as an option.
  * The user can always simulate this by using serial #s for facts.
  *
  * @returns null if not found, the found token otherwise.
  */
 protected final Token findInMemory(TokenVector v, Token t) {
   Token tmp;
   int size = v.size();
   for (int i = 0; i < size; i++) {
     tmp = v.elementAt(i);
     if (t.sortcode != tmp.sortcode) continue;
     if (t.data_equals(tmp)) return tmp;
   }
   return null;
 }
Example #3
0
 /**
  * Run all the tests on a given (left) token and every token in the right memory. For the true
  * ones, assemble a composite token and pass it along to the successors.
  */
 protected void runTestsVaryRight(Token lt) throws ReteException {
   int size = right.size();
   for (int i = 0; i < size; i++) {
     Token rt = right.elementAt(i);
     Token nt = appendToken(lt, rt);
     if (runTests(lt, rt, nt)) {
       int nsucc = _succ.length;
       for (int j = 0; j < nsucc; j++) {
         Successor s = _succ[j];
         s.node.CallNode(nt, s.callType);
       }
     }
   }
 }
Example #4
0
 /**
  * Run all the tests on a given (right) token and every token in the left memory. For the true
  * ones, assemble a composite token and pass it along to the successors.
  */
 protected void runTestsVaryLeft(Token rt) throws ReteException {
   int size = left.size();
   for (int i = 0; i < size; i++) {
     Token lt = left.elementAt(i);
     Token nt = appendToken(lt, rt);
     if (runTests(lt, rt, nt)) {
       // the new token has the *left* token's tag at birth...
       nt.tag = rt.tag;
       int nsucc = _succ.length;
       for (int j = 0; j < nsucc; j++) {
         Successor s = _succ[j];
         s.node.CallNode(nt, s.callType);
       }
     }
   }
 }