private static ProtobufMessages.NodeMemory writeQueryElementNodeMemory(
      final int nodeId, final Memory memory, final InternalWorkingMemory wm) {
    LeftTupleIterator it = LeftTupleIterator.iterator(wm, ((QueryElementNodeMemory) memory).node);

    ProtobufMessages.NodeMemory.QueryElementNodeMemory.Builder _query =
        ProtobufMessages.NodeMemory.QueryElementNodeMemory.newBuilder();
    for (LeftTuple leftTuple = (LeftTuple) it.next();
        leftTuple != null;
        leftTuple = (LeftTuple) it.next()) {
      InternalFactHandle handle = (InternalFactHandle) leftTuple.getObject();
      FactHandle _handle =
          ProtobufMessages.FactHandle.newBuilder()
              .setId(handle.getId())
              .setRecency(handle.getRecency())
              .build();

      ProtobufMessages.NodeMemory.QueryElementNodeMemory.QueryContext.Builder _context =
          ProtobufMessages.NodeMemory.QueryElementNodeMemory.QueryContext.newBuilder()
              .setTuple(PersisterHelper.createTuple(leftTuple))
              .setHandle(_handle);

      LeftTuple childLeftTuple = leftTuple.getFirstChild();
      while (childLeftTuple != null) {
        RightTuple rightParent = childLeftTuple.getRightParent();
        _context.addResult(
            ProtobufMessages.FactHandle.newBuilder()
                .setId(rightParent.getFactHandle().getId())
                .setRecency(rightParent.getFactHandle().getRecency())
                .build());
        while (childLeftTuple != null && childLeftTuple.getRightParent() == rightParent) {
          // skip to the next child that has a different right parent
          childLeftTuple = childLeftTuple.getLeftParentNext();
        }
      }
      _query.addContext(_context.build());
    }

    return _query.getContextCount() > 0
        ? ProtobufMessages.NodeMemory.newBuilder()
            .setNodeId(nodeId)
            .setNodeType(ProtobufMessages.NodeMemory.NodeType.QUERY_ELEMENT)
            .setQueryElement(_query.build())
            .build()
        : null;
  }
 public QueryElementContext(
     ProtobufMessages.NodeMemory.QueryElementNodeMemory.QueryContext _ctx) {
   this.handle = _ctx.getHandle();
   this.results = new LinkedList<ProtobufMessages.FactHandle>(_ctx.getResultList());
 }
 private static void readNodeMemories(MarshallerReaderContext context, RuleData _session) {
   for (ProtobufMessages.NodeMemory _node : _session.getNodeMemoryList()) {
     Object memory = null;
     switch (_node.getNodeType()) {
       case ACCUMULATE:
         {
           Map<TupleKey, ProtobufMessages.FactHandle> map =
               new HashMap<TupleKey, ProtobufMessages.FactHandle>();
           for (ProtobufMessages.NodeMemory.AccumulateNodeMemory.AccumulateContext _ctx :
               _node.getAccumulate().getContextList()) {
             map.put(PersisterHelper.createTupleKey(_ctx.getTuple()), _ctx.getResultHandle());
           }
           memory = map;
           break;
         }
       case RIA:
         {
           Map<TupleKey, ProtobufMessages.FactHandle> map =
               new HashMap<TupleKey, ProtobufMessages.FactHandle>();
           for (ProtobufMessages.NodeMemory.RIANodeMemory.RIAContext _ctx :
               _node.getRia().getContextList()) {
             map.put(PersisterHelper.createTupleKey(_ctx.getTuple()), _ctx.getResultHandle());
           }
           memory = map;
           break;
         }
       case FROM:
         {
           Map<TupleKey, List<ProtobufMessages.FactHandle>> map =
               new HashMap<TupleKey, List<ProtobufMessages.FactHandle>>();
           for (ProtobufMessages.NodeMemory.FromNodeMemory.FromContext _ctx :
               _node.getFrom().getContextList()) {
             // have to instantiate a modifiable list
             map.put(
                 PersisterHelper.createTupleKey(_ctx.getTuple()),
                 new LinkedList<ProtobufMessages.FactHandle>(_ctx.getHandleList()));
           }
           memory = map;
           break;
         }
       case QUERY_ELEMENT:
         {
           Map<TupleKey, QueryElementContext> map = new HashMap<TupleKey, QueryElementContext>();
           for (ProtobufMessages.NodeMemory.QueryElementNodeMemory.QueryContext _ctx :
               _node.getQueryElement().getContextList()) {
             // we have to use a "cloned" query element context as we need to write on it during
             // deserialization process and the
             // protobuf one is read-only
             map.put(
                 PersisterHelper.createTupleKey(_ctx.getTuple()), new QueryElementContext(_ctx));
           }
           memory = map;
           break;
         }
       default:
         {
           throw new IllegalArgumentException(
               "Unknown node type " + _node.getNodeType() + " while deserializing session.");
         }
     }
     context.nodeMemories.put(_node.getNodeId(), memory);
   }
 }