package org.drools.chance.reteoo.builder; import org.drools.base.ValueType; import org.drools.chance.rule.constraint.core.connectives.ConnectiveCore; import org.drools.chance.reteoo.nodes.*; import org.drools.common.BaseNode; import org.drools.common.BetaConstraints; import org.drools.reteoo.*; import org.drools.reteoo.builder.BuildContext; import org.drools.reteoo.builder.NodeFactory; import org.drools.rule.From; import org.drools.rule.GroupElement; import org.drools.rule.QueryElement; import org.drools.rule.Rule; import org.drools.spi.AlphaNodeFieldConstraint; import org.drools.spi.Constraint; import org.drools.spi.DataProvider; import org.drools.spi.ObjectType; public class ChanceNodeFactory implements NodeFactory { public AlphaNode buildAlphaNode( int id, AlphaNodeFieldConstraint constraint, ObjectSource objectSource, BuildContext context ) { return new ChanceAlphaNode( id, constraint, objectSource, context ); } public TerminalNode buildTerminalNode(int id, LeftTupleSource source, Rule rule, GroupElement subrule, int subruleIndex, BuildContext context) { return new ChanceRuleTerminalNode( id, source, rule, subrule, subruleIndex, context ); } public ObjectTypeNode buildObjectTypeNode( int id, EntryPointNode objectSource, ObjectType objectType, BuildContext context ) { if ( objectType.getValueType().equals( ValueType.TRAIT_TYPE ) ) { ChanceTraitObjectTypeNode otn = new ChanceTraitObjectTypeNode( id, objectSource, objectType, context ); otn.setImperfect( ChanceObjectTypeNode.isImperfect( objectType ) ); return otn; } else { ChanceObjectTypeNode otn = new ChanceObjectTypeNode( id, objectSource, objectType, context ); otn.setImperfect( ChanceObjectTypeNode.isImperfect( objectType ) ); return otn; } } public JoinNode buildJoinNode( int id, LeftTupleSource leftInput, ObjectSource rightInput, BetaConstraints binder, BuildContext context ) { return new ChanceJoinNode( id, leftInput, rightInput, binder, context ); } public TerminalNode buildQueryTerminalNode( int id, LeftTupleSource source, Rule rule, GroupElement subrule, int subruleIndex, BuildContext context ) { return new ChanceQueryTerminalNode( id, source, rule, subrule, subruleIndex, context ); } public QueryElementNode buildQueryElementNode( int id, LeftTupleSource tupleSource, QueryElement qe, boolean tupleMemoryEnabled, boolean openQuery, BuildContext context) { return new ChanceQueryElementNode( id, tupleSource, qe, tupleMemoryEnabled, openQuery, context ); } public LeftInputAdapterNode buildLeftInputAdapterNode( int id, ObjectSource objectSource, BuildContext context ) { // No modification needed for now return new LeftInputAdapterNode( id, objectSource, context ); } public BaseNode buildFromNode( int id, DataProvider dataProvider, LeftTupleSource tupleSource, AlphaNodeFieldConstraint[] alphaNodeFieldConstraints, BetaConstraints betaConstraints, boolean tupleMemoryEnabled, BuildContext context, From from ) { return new ChanceFromNode( id, dataProvider, tupleSource, alphaNodeFieldConstraints, betaConstraints, tupleMemoryEnabled, context, from ); } public LogicalAplhaOperatorNode buildLogicalAlphaOperatorNode(int id, String label, ConnectiveCore conn, int arity, ObjectSource objectSource, BuildContext context) { int[] argIndexes = analyzeAlphaEvaluationSources( context, arity ); return new LogicalAplhaOperatorNode( id, label, conn, argIndexes, arity, objectSource, context ); } public LogicalBetaOperatorNode buildLogicalBetaOperatorNode( int id, String label, ConnectiveCore conn, int arity, LeftTupleSource tupleSource, BuildContext context ) { int[] argIndexes = analyzeBetaEvaluationSources( context, arity ); return new LogicalBetaOperatorNode( id, label, conn, arity, argIndexes, tupleSource, context ); } public BaseNode buildDelayedEvaluationNode( int nextId, Constraint constraint, ObjectSource objectSource, BuildContext context ) { return new DelayedEvaluationNode( nextId, constraint, objectSource, context ); } private int[] analyzeAlphaEvaluationSources( BuildContext context, int arity ) { int[] indexes = new int[ arity ]; ObjectSource src = context.getObjectSource(); for ( int j = 0; j < arity; j++ ) { // System.out.println( "ChancePatternBuilder : Preparing arg from node " + src); indexes[ arity - j - 1 ] = src.getId(); if ( j != arity-1 ) { if ( src instanceof LogicalAplhaOperatorNode ) { src = consume( src ); } else { src = skip( src ); } } } return indexes; } private ObjectSource consume( ObjectSource src ) { int subArity = ( (LogicalAplhaOperatorNode) src ).getArity(); src = skip( src ); for ( int j = 0; j < subArity; j++ ) { if ( src instanceof LogicalAplhaOperatorNode ) { src = consume( src ); } else { src = skip( src ); } } return src; } private ObjectSource skip( ObjectSource src ) { src = src.getParentObjectSource(); return src; } private int[] analyzeBetaEvaluationSources( BuildContext context, int arity ) { int[] indexes = new int[ arity ]; LeftTupleSource src = context.getTupleSource(); for ( int j = 0; j < arity; j++ ) { // System.out.println( "ChancePatternBuilder : Preparing arg from node " + src); if ( src instanceof BetaNode ) { indexes[ arity - j - 1 ] = ((BetaNode) src).unwrapRightInput().getId(); } else if ( src instanceof LeftInputAdapterNode ) { indexes[ arity - j - 1 ] = ((LeftInputAdapterNode) src).getParentObjectSource().getId(); } else if ( src instanceof QueryElementNode ) { indexes[ arity - j - 1 ] = src.getId(); } else if ( src instanceof FromNode ) { indexes[ arity - j - 1 ] = src.getId(); } if ( j != arity-1 ) { if ( src instanceof LogicalBetaOperatorNode ) { src = consumeBeta( src ); } else { src = skipBeta( src ); } } } return indexes; } private LeftTupleSource consumeBeta( LeftTupleSource src ) { int subArity = ( (LogicalBetaOperatorNode) src ).getArity(); src = skipBeta( src ); for ( int j = 0; j < subArity; j++ ) { if ( src instanceof LogicalBetaOperatorNode) { src = consumeBeta( src ); } else { src = skipBeta( src ); } } return src; } private LeftTupleSource skipBeta( LeftTupleSource src ) { if ( src instanceof BetaNode ) { return ((BetaNode) src).getLeftTupleSource(); } else if ( src instanceof QueryElementNode ) { return ((QueryElementNode) src).getLeftTupleSource(); } else if ( src instanceof FromNode ) { return ((FromNode) src).getLeftTupleSource(); } else { throw new UnsupportedOperationException( "Can't navigate this path " ); } } }