package org.drools.chance.reteoo.nodes; import org.drools.chance.rule.constraint.core.connectives.ConnectiveCore; import org.drools.chance.degree.Degree; import org.drools.chance.degree.simple.SimpleDegree; import org.drools.chance.evaluation.CompositeEvaluation; import org.drools.chance.evaluation.DelayedEvaluationImpl; import org.drools.chance.evaluation.Evaluation; import org.drools.chance.reteoo.ChanceFactHandle; import org.drools.common.InternalFactHandle; import org.drools.common.InternalWorkingMemory; import org.drools.common.PropagationContextImpl; import org.drools.reteoo.*; import org.drools.reteoo.builder.BuildContext; import org.drools.spi.PropagationContext; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Arrays; import java.util.List; //TODO do not extend AlphaNode! public class LogicalAplhaOperatorNode extends ChanceAlphaNode implements ObjectSinkNode { private ObjectSinkNode previousRightTupleSinkNode; private ObjectSinkNode nextRightTupleSinkNode; private ConnectiveCore connective; private int arity; private int[] argIndexes; private String label; public LogicalAplhaOperatorNode( int id, String label, ConnectiveCore conn, int[] argIndexes, int arity, ObjectSource objectSource, BuildContext context ) { super( id, null, objectSource, context ); this.connective = conn; this.arity = arity; this.argIndexes = argIndexes; this.label = label; } public int getArity() { return arity; } public ConnectiveCore getConnective() { return connective; } public short getType() { return NodeTypeEnums.OperatorNode; } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { super.readExternal( in ); connective = (ConnectiveCore) in.readObject(); arity = in.readInt(); argIndexes = (int[]) in.readObject(); } public void writeExternal(ObjectOutput out) throws IOException { super.writeExternal(out); out.writeObject( connective ); out.writeInt( arity ); out.writeObject( argIndexes ); } /* * (non-Javadoc) * * @see org.drools.reteoo.BaseNode#attach() */ public void attach() { this.source.addObjectSink( this ); } public void attach( final InternalWorkingMemory[] workingMemories ) { attach(); for ( int i = 0, length = workingMemories.length; i < length; i++ ) { final InternalWorkingMemory workingMemory = workingMemories[i]; final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(), PropagationContext.RULE_ADDITION, null, null, null ); this.source.updateSink( this, propagationContext, workingMemory ); } } public void assertObject(final InternalFactHandle factHandle, final PropagationContext context, final InternalWorkingMemory workingMemory) { ChanceFactHandle chandle = (ChanceFactHandle) factHandle; Evaluation agg = reevaluate(chandle); chandle.addEvaluation( this.id, agg ); boolean canPropagate = agg.getDegree().toBoolean(); if ( canPropagate ) { this.sink.propagateAssertObject( factHandle, context, workingMemory ); } } public void modifyObject(final InternalFactHandle factHandle, final ModifyPreviousTuples modifyPreviousTuples, final PropagationContext context, final InternalWorkingMemory workingMemory) { ChanceFactHandle chandle = (ChanceFactHandle) factHandle; Evaluation agg = reevaluate( chandle ); chandle.addEvaluation( this.id, agg ); if ( agg.getDegree().toBoolean() ) { this.sink.propagateModifyObject(factHandle, modifyPreviousTuples, context, workingMemory); } } private Evaluation reevaluate( ChanceFactHandle chandle ) { Degree[] bits = new Degree[arity]; Evaluation[] children = new Evaluation[arity]; for ( int j = 0; j < arity; j ++ ) { Evaluation arg = chandle.getCachedEvaluation( this.argIndexes[j] ); children[ j ] = arg != null ? arg : new DelayedEvaluationImpl( this.argIndexes[j] ); bits[ j ] = arg != null ? arg.getDegree() : SimpleDegree.TRUE; } Degree res = this.connective.eval( bits ); // System.err.println( "LOP" + res ); return new CompositeEvaluation( this.id, connective.toString() + Arrays.toString( children ), res, connective, children, label ); } public void byPassModifyToBetaNode ( final InternalFactHandle factHandle, final ModifyPreviousTuples modifyPreviousTuples, final PropagationContext context, final InternalWorkingMemory workingMemory) { sink.byPassModifyToBetaNode( factHandle, modifyPreviousTuples, context, workingMemory ); } public void updateSink(final ObjectSink sink, final PropagationContext context, final InternalWorkingMemory workingMemory) { this.source.updateSink( sink, context, workingMemory ); } public String toString() { return "[" + getId() +"] Operator " + connective; } public int hashCode() { return id; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; LogicalAplhaOperatorNode that = (LogicalAplhaOperatorNode) o; if (connective != that.connective) return false; if (arity != that.arity) return false; return true; } /** * Returns the next node * @return * The next ObjectSinkNode */ public ObjectSinkNode getNextObjectSinkNode() { return this.nextRightTupleSinkNode; } /** * Sets the next node * @param next * The next ObjectSinkNode */ public void setNextObjectSinkNode(final ObjectSinkNode next) { this.nextRightTupleSinkNode = next; } /** * Returns the previous node * @return * The previous ObjectSinkNode */ public ObjectSinkNode getPreviousObjectSinkNode() { return this.previousRightTupleSinkNode; } /** * Sets the previous node * @param previous * The previous ObjectSinkNode */ public void setPreviousObjectSinkNode(final ObjectSinkNode previous) { this.previousRightTupleSinkNode = previous; } public long calculateDeclaredMask(List<String> settableProperties) { return Long.MAX_VALUE; } @Override public long getDeclaredMask() { return declaredMask; } @Override public void addObjectSink(final ObjectSink objectSink) { super.addObjectSink(objectSink); } }