/**
   * 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 (context.getType() == PropagationContext.MODIFICATION
        && this.skipOnModify
        && context.getDormantActivations() == 0) {
      // we do this after the shadowproxy update, just so that its up to date for the future
      return;
    }

    if (this.objectMemoryEnabled) {
      final ObjectHashSet memory = (ObjectHashSet) workingMemory.getNodeMemory(this);
      memory.add(factHandle, false);
    }
    this.sink.propagateAssertObject(factHandle, context, workingMemory);

    if (this.expirationOffset >= 0) {
      // schedule expiration
      WorkingMemoryReteExpireAction expire = new WorkingMemoryReteExpireAction(factHandle, this);
      TimerService clock = workingMemory.getTimerService();

      long nextTimestamp = clock.getCurrentTime() + this.expirationOffset;
      JobContext jobctx = new ExpireJobContext(expire, workingMemory);
      JobHandle handle = clock.scheduleJob(job, jobctx, new PointInTimeTrigger(nextTimestamp));
      jobctx.setJobHandle(handle);
    }
  }