Esempio n. 1
0
  public void retract(
      final org.drools.FactHandle factHandle,
      final boolean removeLogical,
      final boolean updateEqualsMap,
      final Rule rule,
      final Activation activation)
      throws FactException {
    if (factHandle == null) {
      throw new IllegalArgumentException("FactHandle cannot be null ");
    }
    try {
      this.ruleBase.readLock();
      this.lock.lock();
      this.wm.startOperation();
      this.ruleBase.executeQueuedActions();

      InternalFactHandle handle = (InternalFactHandle) factHandle;
      if (handle.getId() == -1) {
        // can't retract an already retracted handle
        return;
      }

      // the handle might have been disconnected, so reconnect if it has
      if (handle.isDisconnected()) {
        handle = this.objectStore.reconnect(handle);
      }

      if (handle.getEntryPoint() != this) {
        throw new IllegalArgumentException(
            "Invalid Entry Point. You updated the FactHandle on entry point '"
                + handle.getEntryPoint().getEntryPointId()
                + "' instead of '"
                + getEntryPointId()
                + "'");
      }

      final Object object = handle.getObject();

      final ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf(this.entryPoint, object);

      if (typeConf.isSupportsPropertyChangeListeners()) {
        removePropertyChangeListener(handle, true);
      }

      if (activation != null) {
        // release resources so that they can be GC'ed
        activation.getPropagationContext().releaseResources();
      }
      final PropagationContext propagationContext =
          new PropagationContextImpl(
              this.wm.getNextPropagationIdCounter(),
              PropagationContext.RETRACTION,
              rule,
              (activation == null) ? null : activation.getTuple(),
              handle,
              this.wm.agenda.getActiveActivations(),
              this.wm.agenda.getDormantActivations(),
              this.entryPoint);

      this.entryPointNode.retractObject(handle, propagationContext, typeConf, this.wm);

      if (typeConf.isTMSEnabled()) {
        TruthMaintenanceSystem tms = wm.getTruthMaintenanceSystem();

        // Update the equality key, which maintains a list of stated
        // FactHandles
        final EqualityKey key = handle.getEqualityKey();

        // Its justified so attempt to remove any logical dependencies
        // for
        // the handle
        if (key.getStatus() == EqualityKey.JUSTIFIED) {
          tms.removeLogicalDependencies(handle);
        }

        key.removeFactHandle(handle);
        handle.setEqualityKey(null);

        // If the equality key is now empty, then remove it
        if (key.isEmpty()) {
          tms.remove(key);
        }
      }

      propagationContext.evaluateActionQueue(this.wm);

      this.wm.workingMemoryEventSupport.fireObjectRetracted(
          propagationContext, handle, object, this.wm);

      this.objectStore.removeHandle(handle);

      this.handleFactory.destroyFactHandle(handle);

      this.wm.executeQueuedActions();

      if (rule == null) {
        // This is not needed for internal WM actions as the firing rule will unstage
        this.wm.getAgenda().unstageActivations();
      }
    } finally {
      this.wm.endOperation();
      this.lock.unlock();
      this.ruleBase.readUnlock();
    }
  }
Esempio n. 2
0
  public void update(
      org.drools.FactHandle factHandle,
      final Object object,
      final long mask,
      final Activation activation)
      throws FactException {
    try {
      this.ruleBase.readLock();
      this.lock.lock();
      this.wm.startOperation();
      this.ruleBase.executeQueuedActions();

      InternalFactHandle handle = (InternalFactHandle) factHandle;

      // the handle might have been disconnected, so reconnect if it has
      if (handle.isDisconnected()) {
        handle = this.objectStore.reconnect(factHandle);
      }

      final Object originalObject = handle.getObject();

      if (handle.getEntryPoint() != this) {
        throw new IllegalArgumentException(
            "Invalid Entry Point. You updated the FactHandle on entry point '"
                + handle.getEntryPoint().getEntryPointId()
                + "' instead of '"
                + getEntryPointId()
                + "'");
      }

      final ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf(this.entryPoint, object);

      // only needed if we maintain tms, but either way we must get it before we do the retract
      int status = -1;
      if (typeConf.isTMSEnabled()) {
        status = handle.getEqualityKey().getStatus();
      }

      if (handle.getId() == -1
          || object == null
          || (handle.isEvent() && ((EventFactHandle) handle).isExpired())) {
        // the handle is invalid, most likely already retracted, so return and we cannot assert a
        // null object
        return;
      }

      if (activation != null) {
        // release resources so that they can be GC'ed
        activation.getPropagationContext().releaseResources();
      }

      if (originalObject != object
          || !AssertBehaviour.IDENTITY.equals(
              this.ruleBase.getConfiguration().getAssertBehaviour())) {
        this.objectStore.removeHandle(handle);

        // set anyway, so that it updates the hashCodes
        handle.setObject(object);
        this.objectStore.addHandle(handle, object);
      }

      if (typeConf.isTMSEnabled()) {

        // the hashCode and equality has changed, so we must update the
        // EqualityKey
        EqualityKey key = handle.getEqualityKey();
        key.removeFactHandle(handle);

        TruthMaintenanceSystem tms = wm.getTruthMaintenanceSystem();

        // If the equality key is now empty, then remove it
        if (key.isEmpty()) {
          tms.remove(key);
        }

        // now use an existing EqualityKey, if it exists, else create a new one
        key = tms.get(object);
        if (key == null) {
          key = new EqualityKey(handle, status);
          tms.put(key);
        } else {
          key.addFactHandle(handle);
        }

        handle.setEqualityKey(key);
      }

      this.handleFactory.increaseFactHandleRecency(handle);

      Rule rule = activation == null ? null : activation.getRule();

      final PropagationContext propagationContext =
          new PropagationContextImpl(
              this.wm.getNextPropagationIdCounter(),
              PropagationContext.MODIFICATION,
              rule,
              (activation == null) ? null : activation.getTuple(),
              handle,
              this.wm.agenda.getActiveActivations(),
              this.wm.agenda.getDormantActivations(),
              entryPoint,
              mask);

      this.entryPointNode.modifyObject(handle, propagationContext, typeConf, this.wm);

      propagationContext.evaluateActionQueue(this.wm);

      this.wm.workingMemoryEventSupport.fireObjectUpdated(
          propagationContext, factHandle, originalObject, object, this.wm);

      this.wm.executeQueuedActions();

      if (rule == null) {
        // This is not needed for internal WM actions as the firing rule will unstage
        this.wm.getAgenda().unstageActivations();
      }
    } finally {
      this.wm.endOperation();
      this.lock.unlock();
      this.ruleBase.readUnlock();
    }
  }