public void dispose() { if (dynamicFacts != null) { // first we check for facts that were inserted into the working memory // using the old API and setting a per instance dynamic flag and remove the // session from the listeners list in the bean for (InternalFactHandle handle : dynamicFacts) { removePropertyChangeListener(handle, false); } dynamicFacts = null; } for (ObjectTypeConf conf : this.typeConfReg.values()) { // then, we check if any of the object types were configured using the // @propertyChangeSupport annotation, and clean them up if (conf.isDynamic() && conf.isSupportsPropertyChangeListeners()) { // it is enough to iterate the facts on the concrete object type nodes // only, as the facts will always be in their concrete object type nodes // even if they were also asserted into higher level OTNs as well ObjectTypeNode otn = conf.getConcreteObjectTypeNode(); final ObjectHashSet memory = ((ObjectTypeNodeMemory) this.getInternalWorkingMemory().getNodeMemory(otn)).memory; Iterator it = memory.iterator(); for (ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next()) { InternalFactHandle handle = (InternalFactHandle) entry.getValue(); removePropertyChangeListener(handle, false); } } } }
protected FactHandle insert( final Object object, final boolean dynamic, boolean logical, final Rule rule, final Activation activation) throws FactException { if (object == null) { // you cannot assert a null object return null; } try { this.wm.startOperation(); ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf(this.entryPoint, object); if (logical && !typeConf.isTMSEnabled()) { enableTMS(object, typeConf); } InternalFactHandle handle = null; if (this.wm.isSequential()) { handle = createHandle(object, typeConf); insert(handle, object, rule, activation, typeConf); return handle; } try { this.ruleBase.readLock(); this.lock.lock(); // check if the object already exists in the WM handle = this.objectStore.getHandleForObject(object); if (typeConf.isTMSEnabled()) { EqualityKey key; TruthMaintenanceSystem tms = wm.getTruthMaintenanceSystem(); if (handle == null) { // lets see if the object is already logical asserted key = tms.get(object); } else { // Object is already asserted, so check and possibly correct its // status and then return the handle key = handle.getEqualityKey(); if (key.getStatus() == EqualityKey.STATED) { // return null as you cannot justify a stated object. return handle; } if (!logical) { // this object was previously justified, so we have to override it to stated key.setStatus(EqualityKey.STATED); tms.removeLogicalDependencies(handle); } else { // this was object is already justified, so just add new logical dependency tms.addLogicalDependency( handle, activation, activation.getPropagationContext(), rule); } return handle; } // At this point we know the handle is null if (key == null) { handle = createHandle(object, typeConf); key = createEqualityKey(handle); tms.put(key); if (!logical) { key.setStatus(EqualityKey.STATED); } else { key.setStatus(EqualityKey.JUSTIFIED); tms.addLogicalDependency( handle, activation, activation.getPropagationContext(), rule); } } else if (!logical) { if (key.getStatus() == EqualityKey.JUSTIFIED) { // Its previous justified, so switch to stated and remove logical dependencies final InternalFactHandle justifiedHandle = key.getFactHandle(); tms.removeLogicalDependencies(justifiedHandle); if (this.wm.discardOnLogicalOverride) { // override, setting to new instance, and return // existing handle key.setStatus(EqualityKey.STATED); handle = key.getFactHandle(); if (AssertBehaviour.IDENTITY.equals( this.ruleBase.getConfiguration().getAssertBehaviour())) { // as assertMap may be using an "identity" // equality comparator, // we need to remove the handle from the map, // before replacing the object // and then re-add the handle. Otherwise we may // end up with a leak. this.objectStore.updateHandle(handle, object); } return handle; } else { // override, then instantiate new handle for // assertion key.setStatus(EqualityKey.STATED); handle = createHandle(object, typeConf); handle.setEqualityKey(key); key.addFactHandle(handle); } } else { handle = createHandle(object, typeConf); key.addFactHandle(handle); handle.setEqualityKey(key); } } else { if (key.getStatus() == EqualityKey.JUSTIFIED) { // only add as logical dependency if this wasn't previously stated tms.addLogicalDependency( key.getFactHandle(), activation, activation.getPropagationContext(), rule); return key.getFactHandle(); } else { // You cannot justify a previously stated equality equal object, so return null return null; } } } else { if (handle != null) { return handle; } handle = createHandle(object, typeConf); } // if the dynamic parameter is true or if the user declared the fact type with the meta tag: // @propertyChangeSupport if (dynamic || typeConf.isDynamic()) { addPropertyChangeListener(handle, dynamic); } insert(handle, object, rule, activation, typeConf); } finally { this.lock.unlock(); this.ruleBase.readUnlock(); } return handle; } finally { this.wm.endOperation(); } }