Skip to content

Commit

Permalink
JBRULES-3430: fixing handling of disconnected fact handles during ser…
Browse files Browse the repository at this point in the history
…ialization

(cherry picked from commit 14f0e38453f8d8d78e65740928ca121d85ed2701)
  • Loading branch information
etirelli committed Apr 2, 2012
1 parent 11e6cfa commit 13f361f
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 49 deletions.
Expand Up @@ -18,12 +18,10 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
Expand All @@ -34,13 +32,10 @@
import org.drools.command.Setter;
import org.drools.command.impl.GenericCommand;
import org.drools.command.impl.KnowledgeCommandContext;
import org.drools.common.DefaultFactHandle;
import org.drools.common.InternalFactHandle;
import org.drools.common.DisconnectedFactHandle;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.rule.FactHandle;
import org.drools.runtime.rule.WorkingMemoryEntryPoint;
import org.drools.xml.jaxb.util.JaxbListAdapter;
import org.drools.xml.jaxb.util.JaxbListWrapper;
import org.mvel2.MVEL;

@XmlAccessorType(XmlAccessType.NONE)
Expand All @@ -55,7 +50,7 @@ public class ModifyCommand
public static boolean ALLOW_MODIFY_EXPRESSIONS = true;


private FactHandle handle;
private DisconnectedFactHandle handle;


@XmlJavaTypeAdapter(JaxbSetterAdapter.class)
Expand All @@ -67,13 +62,13 @@ public ModifyCommand() {

public ModifyCommand(FactHandle handle,
List<Setter> setters) {
this.handle = handle;
this.handle = DisconnectedFactHandle.newFrom( handle );
this.setters = setters;
}

public Object execute(Context context) {
StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
WorkingMemoryEntryPoint wmep = ksession.getWorkingMemoryEntryPoint( ((InternalFactHandle)handle).getEntryPoint().getEntryPointId() );
WorkingMemoryEntryPoint wmep = ksession.getWorkingMemoryEntryPoint( handle.getEntryPointId() );

Object object = wmep.getObject( this.handle );
MVEL.eval( getMvelExpr(),
Expand All @@ -90,7 +85,7 @@ public FactHandle getFactHandle() {

@XmlAttribute(name="fact-handle", required=true)
public void setFactHandleFromString(String factHandleId) {
handle = new DefaultFactHandle(factHandleId);
handle = new DisconnectedFactHandle(factHandleId);
}

public String getFactHandleFromString() {
Expand Down
Expand Up @@ -24,6 +24,7 @@
import org.drools.command.impl.GenericCommand;
import org.drools.command.impl.KnowledgeCommandContext;
import org.drools.common.DefaultFactHandle;
import org.drools.common.DisconnectedFactHandle;
import org.drools.common.InternalFactHandle;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.rule.FactHandle;
Expand All @@ -32,18 +33,18 @@
public class RetractCommand
implements GenericCommand<Object> {

private FactHandle handle;
private DisconnectedFactHandle handle;

public RetractCommand() {
}

public RetractCommand(FactHandle handle) {
this.handle = handle;
this.handle = DisconnectedFactHandle.newFrom( handle );
}

public Object execute(Context context) {
StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
ksession.getWorkingMemoryEntryPoint( ((InternalFactHandle)handle).getEntryPoint().getEntryPointId() ).retract( handle );
ksession.getWorkingMemoryEntryPoint( handle.getEntryPointId() ).retract( handle );
return null;
}

Expand All @@ -53,7 +54,7 @@ public FactHandle getFactHandle() {

@XmlAttribute(name="fact-handle", required=true)
public void setFactHandleFromString(String factHandleId) {
handle = new DefaultFactHandle(factHandleId);
handle = new DisconnectedFactHandle(factHandleId);
}

public String getFactHandleFromString() {
Expand Down
Expand Up @@ -19,29 +19,31 @@
import org.drools.command.Context;
import org.drools.command.impl.GenericCommand;
import org.drools.command.impl.KnowledgeCommandContext;
import org.drools.common.DisconnectedFactHandle;
import org.drools.common.InternalFactHandle;
import org.drools.reteoo.ReteooWorkingMemory;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.rule.FactHandle;

public class UpdateCommand
implements GenericCommand<Object> {

private FactHandle handle;
private static final long serialVersionUID = 3255044102543531497L;

private DisconnectedFactHandle handle;
private Object object;
private String entryPoint;

public UpdateCommand(FactHandle handle,
Object object) {
this.handle = handle;
this.handle = DisconnectedFactHandle.newFrom( handle );
this.object = object;
}

public Object execute(Context context) {
StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();

ksession.getWorkingMemoryEntryPoint( ((InternalFactHandle)handle).getEntryPoint().getEntryPointId() ).update( handle,
object );
ksession.getWorkingMemoryEntryPoint( handle.getEntryPointId() ).update( handle,
object );
return null;
}

Expand Down
Expand Up @@ -6,50 +6,74 @@

import org.drools.reteoo.LeftTuple;
import org.drools.reteoo.RightTuple;
import org.drools.runtime.rule.FactHandle;
import org.drools.runtime.rule.WorkingMemoryEntryPoint;

@XmlAccessorType(XmlAccessType.NONE)
public class DisconnectedFactHandle
implements
InternalFactHandle {
implements
InternalFactHandle {

private int id;
private int identityHashCode;
private int objectHashCode;
private long recency;
private int id;
private int identityHashCode;
private int objectHashCode;
private long recency;
private Object object;
private String entryPointId;

protected DisconnectedFactHandle() {}
protected DisconnectedFactHandle() {
}

public DisconnectedFactHandle(int id,
int identityHashCode,
int objectHashCode,
long recency,
String entryPointId,
Object object) {
this( id, identityHashCode, objectHashCode, recency );
this.id = id;
this.identityHashCode = identityHashCode;
this.objectHashCode = objectHashCode;
this.recency = recency;
this.entryPointId = entryPointId;
this.object = object;
}

public DisconnectedFactHandle(int id,
int identityHashCode,
int objectHashCode,
long recency,
Object object) {
this( id,
identityHashCode,
objectHashCode,
recency,
null,
object );
}

public DisconnectedFactHandle(int id,
int identityHashCode,
int objectHashCode,
long recency) {
this.id = id;
this.identityHashCode = identityHashCode;
this.objectHashCode = objectHashCode;
this.recency = recency;
this( id,
identityHashCode,
objectHashCode,
recency,
null,
null );
}

public DisconnectedFactHandle(String externalFormat) {
String[] elements = externalFormat.split( ":" );
if ( elements.length != 5 ) {
if ( elements.length < 6 ) {
throw new IllegalArgumentException( "externalFormat did not have enough elements" );
}

this.id = Integer.parseInt( elements[1] );
this.identityHashCode = Integer.parseInt( elements[2] );
this.objectHashCode = Integer.parseInt( elements[3] );
this.recency = Long.parseLong( elements[4] );
this.entryPointId = elements[5];
}

public int getId() {
Expand Down Expand Up @@ -132,46 +156,43 @@ public DefaultFactHandle clone() {
}

public String toExternalForm() {
return "0:" + this.id + ":" + this.identityHashCode + ":" + this.objectHashCode + ":" + this.recency;
return "0:" + this.id + ":" + this.identityHashCode + ":" + this.objectHashCode + ":" + this.recency + ":" + this.entryPointId;
}
@XmlAttribute(name="external-form")

@XmlAttribute(name = "external-form")
public String getExternalForm() {
return toExternalForm();
}


public LeftTuple getFirstLeftTuple() {
throw new UnsupportedOperationException( "DisonnectedFactHandle does not support this method" );
}


public RightTuple getFirstRightTuple() {
throw new UnsupportedOperationException( "DisonnectedFactHandle does not support this method" );
}


public RightTuple getLastRightTuple() {
throw new UnsupportedOperationException( "DisonnectedFactHandle does not support this method" );
}

public String toTupleTree(int indent) {
return null;
}

public boolean isDisconnected() {
throw new UnsupportedOperationException("Not supported yet.");
return true;
}

public void disconnect() {
throw new UnsupportedOperationException("Not supported yet.");
throw new UnsupportedOperationException( "Not supported yet." );
}

public void addLastLeftTuple( LeftTuple leftTuple ) {
public void addLastLeftTuple(LeftTuple leftTuple) {
throw new UnsupportedOperationException( "DisonnectedFactHandle does not support this method" );
}

public void removeLeftTuple( LeftTuple leftTuple ) {
public void removeLeftTuple(LeftTuple leftTuple) {
throw new UnsupportedOperationException( "DisonnectedFactHandle does not support this method" );
}

Expand All @@ -183,16 +204,34 @@ public void clearRightTuples() {
throw new UnsupportedOperationException( "DisonnectedFactHandle does not support this method" );
}

public void addFirstRightTuple( RightTuple rightTuple ) {
public void addFirstRightTuple(RightTuple rightTuple) {
throw new UnsupportedOperationException( "DisonnectedFactHandle does not support this method" );
}

public void addLastRightTuple( RightTuple rightTuple ) {
public void addLastRightTuple(RightTuple rightTuple) {
throw new UnsupportedOperationException( "DisonnectedFactHandle does not support this method" );
}

public void removeRightTuple( RightTuple rightTuple ) {
public void removeRightTuple(RightTuple rightTuple) {
throw new UnsupportedOperationException( "DisonnectedFactHandle does not support this method" );
}

public String getEntryPointId() {
return entryPointId;
}

public static DisconnectedFactHandle newFrom( FactHandle handle ) {
if( handle instanceof DisconnectedFactHandle ) {
return (DisconnectedFactHandle) handle;
} else {
InternalFactHandle ifh = (InternalFactHandle) handle;
return new DisconnectedFactHandle(ifh.getId(),
ifh.getIdentityHashCode(),
ifh.getObjectHashCode(),
ifh.getRecency(),
ifh.getEntryPoint() != null ? ifh.getEntryPoint().getEntryPointId() : null,
null );
}
}

}
Expand Up @@ -384,12 +384,13 @@ public void update(org.drools.FactHandle factHandle,
this.ruleBase.executeQueuedActions();

InternalFactHandle handle = (InternalFactHandle) factHandle;
final Object originalObject = handle.getObject();

// 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() + "'" );
Expand Down

0 comments on commit 13f361f

Please sign in to comment.