<commit_before>package org.drools.chance.rule.builder;

import org.drools.chance.factmodel.Imperfect;
import org.drools.chance.common.ImperfectField;
import org.drools.chance.core.util.IntHashMap;
import org.drools.chance.reteoo.nodes.ChanceObjectTypeNode;
import org.drools.compiler.DescrBuildError;
import org.drools.lang.descr.*;
import org.drools.rule.Declaration;
import org.drools.rule.Pattern;
import org.drools.rule.builder.PatternBuilder;
import org.drools.rule.builder.RuleBuildContext;
import org.drools.spi.InternalReadAccessor;

import java.util.ArrayList;
import java.util.List;

public class ChanceRulePatternBuilder extends PatternBuilder {


    public ChanceRulePatternBuilder() {
        super();
    }



    protected void processConstraintsAndBinds( final RuleBuildContext context,
                                               final PatternDescr patternDescr,
                                               final Pattern pattern ) {

        List constraints = patternDescr.getConstraint().getDescrs();
        List<? extends BaseDescr> temp = new ArrayList<BaseDescr>( patternDescr.getConstraint().getDescrs() );
        List<ConstraintConnectiveDescr> rootConstraints = new ArrayList<ConstraintConnectiveDescr>();

        IntHashMap<Boolean> impFlags = new IntHashMap<Boolean>();
        IntHashMap<Boolean> posFlags = new IntHashMap<Boolean>();

        boolean hasImperfectConstraint = ( patternDescr.getAnnotation( Imperfect.class.getSimpleName() ) != null );
        for ( BaseDescr b : temp ) {
            String expression;
            boolean isPositional = false;
            if ( b instanceof BindingDescr ) {
                BindingDescr bind = (BindingDescr) b;
                expression = bind.getVariable() + (bind.isUnification() ? " := " : " : ") + bind.getExpression();
            } else if ( b instanceof ExprConstraintDescr ) {
                ExprConstraintDescr descr = (ExprConstraintDescr) b;
                expression = descr.getExpression();
                isPositional = descr.getType() == ExprConstraintDescr.Type.POSITIONAL;
            } else {
                expression = b.getText();
            }


            ConstraintConnectiveDescr result = parseExpression( context,
                    patternDescr,
                    b,
                    expression );

            boolean isImperfect = ChanceObjectTypeNode.isImperfect(pattern.getObjectType()) || analyzeConstraintConnective( result, context, pattern );

            if ( isImperfect ) {
                hasImperfectConstraint = true;
                if ( ! isPositional && result != null ) {
                    rootConstraints.add( result );

                    int index = constraints.indexOf( b );
                    int k = index;
                    impFlags.put( k, true );
                    posFlags.put( k, false );

                    constraints.remove( index );
                    for ( BaseDescr sub : expand( result ) ) {
                        constraints.add( index, sub );
                        ++k;
                        impFlags.put( k, true );
                        posFlags.put( k, false );
                    }
                }
            } else {
                int index = constraints.indexOf( b );
                impFlags.put( index, false );

                rootConstraints.add( result );
                if (! isPositional) {
                    constraints.remove( index );
                    constraints.add( index, result );
                }

                if ( ! isPositional ) {
                    posFlags.put( index, false );
                } else {
                    posFlags.put( index, true );
                }
            }

        }

        // Add the pattern-level "and"
        if ( hasImperfectConstraint ) {
            ConstraintConnectiveDescr root = new ConstraintConnectiveDescr( ConnectiveType.AND );
            // mock "isA" to increase cardinality by 1
            root.addDescr( new RelationalExprDescr( "isA",
                    false,
                    null,
                    new AtomicExprDescr( "this" ),
                    new AtomicExprDescr( patternDescr.getObjectType() ) ) );

            for ( BaseDescr rootChild : rootConstraints ) {
                root.addDescr( rootChild );
            }
            if ( patternDescr.getAnnotation( Imperfect.class.getSimpleName() ) != null ) {
                root.addAnnotation( patternDescr.getAnnotation( Imperfect.class.getSimpleName() ) );
            }
            constraints.add( root );
            impFlags.put( constraints.size() - 1, true );
            posFlags.put( constraints.size() - 1, false );
        }


        int index = 0;
        for ( BaseDescr b : patternDescr.getDescrs() ) {
            boolean isPositional = posFlags.get( index );

                        
            if ( b instanceof BindingDescr ) {
                // it is just a bind, so build it
                buildRuleBindings( context,
                        patternDescr,
                        pattern,
                        (BindingDescr) b );
            } else if ( b instanceof ConstraintConnectiveDescr ) {
                if ( impFlags.get( index ) == true ) {
                    build(context,
                            patternDescr,
                            pattern,
                            (ConstraintConnectiveDescr) b);
                } else {

                    ConstraintConnectiveDescr result = (ConstraintConnectiveDescr) b;
                    if ( result.getDescrs().size() == 1 && result.getDescrs().get( 0 ) instanceof BindingDescr ) {
                        // it is just a bind, so build it
                        buildRuleBindings( context,
                                patternDescr,
                                pattern,
                                (BindingDescr) result.getDescrs().get( 0 ) );
                    } else {


                        super.build(context,
                                patternDescr,
                                pattern,
                                (ConstraintConnectiveDescr) b);
                    }
                }
            }  else if ( isPositional ) {
                processPositional(context,
                        patternDescr,
                        pattern,
                        (ExprConstraintDescr) b);
            } else {
                // need to build the actual constraint
                buildCcdDescr( context,
                        patternDescr,
                        pattern,
                        b );
            }

            index++;
        }

//        combineConstraints(context, pattern);
    }


    protected void processDuplicateBindings( boolean isUnification,
                                                 PatternDescr patternDescr,
                                                 Pattern pattern,
                                                 BaseDescr original,
                                                 String leftExpression,
                                                 String rightIdentifier,
                                                 RuleBuildContext context ) {

            if ( isUnification ) {
                String expr = leftExpression + " == " + rightIdentifier;
                ConstraintConnectiveDescr result = parseExpression( context,
                                                                    patternDescr,
                                                                    patternDescr,
                                                                    expr );
                BaseDescr constr = result.getDescrs().get( 0 );
                buildCcdDescr( context,
                        patternDescr,
                        pattern,
                        constr );
            } else {
                // This declaration already exists, so throw an Exception
                context.addError(new DescrBuildError(context.getParentDescr(),
                        patternDescr,
                        null,
                        "Duplicate declaration for variable '" + leftExpression + "' in the rule '" + context.getRule().getName() + "'"));
            }

        }



    private boolean analyzeConstraintConnective( BaseDescr descr, RuleBuildContext context, Pattern pattern ) {
        if ( descr instanceof ConstraintConnectiveDescr ) {
            ConstraintConnectiveDescr ccd = (ConstraintConnectiveDescr) descr;
            if ( ( (ConstraintConnectiveDescr) descr ).getAnnotation( Imperfect.class.getSimpleName() ) != null ) {
                return true;
            }
            for ( BaseDescr child : ccd.getDescrs() ) {
                if ( analyzeConstraintConnective( child, context, pattern ) ) {
                    return true;
                }
            }
        } else if ( descr instanceof RelationalExprDescr ) {
            RelationalExprDescr rel = (RelationalExprDescr) descr;<commit_msg>Chance core : align with interface changes in drools core/compiler (inline casts)<commit_after>package org.drools.chance.rule.builder;

import org.drools.chance.factmodel.Imperfect;
import org.drools.chance.common.ImperfectField;
import org.drools.chance.core.util.IntHashMap;
import org.drools.chance.reteoo.nodes.ChanceObjectTypeNode;
import org.drools.compiler.DescrBuildError;
import org.drools.lang.MVELDumper;
import org.drools.lang.descr.*;
import org.drools.rule.Declaration;
import org.drools.rule.Pattern;
import org.drools.rule.builder.PatternBuilder;
import org.drools.rule.builder.RuleBuildContext;
import org.drools.spi.InternalReadAccessor;

import java.util.ArrayList;
import java.util.List;

public class ChanceRulePatternBuilder extends PatternBuilder {


    public ChanceRulePatternBuilder() {
        super();
    }



    protected void processConstraintsAndBinds( final RuleBuildContext context,
                                               final PatternDescr patternDescr,
                                               final Pattern pattern ) {

        MVELDumper.MVELDumperContext mvelCtx = new MVELDumper.MVELDumperContext().setRuleContext(context);
        List constraints = patternDescr.getConstraint().getDescrs();
        List<? extends BaseDescr> temp = new ArrayList<BaseDescr>( patternDescr.getConstraint().getDescrs() );
        List<ConstraintConnectiveDescr> rootConstraints = new ArrayList<ConstraintConnectiveDescr>();

        IntHashMap<Boolean> impFlags = new IntHashMap<Boolean>();
        IntHashMap<Boolean> posFlags = new IntHashMap<Boolean>();

        boolean hasImperfectConstraint = ( patternDescr.getAnnotation( Imperfect.class.getSimpleName() ) != null );
        for ( BaseDescr b : temp ) {
            String expression;
            boolean isPositional = false;
            if ( b instanceof BindingDescr ) {
                BindingDescr bind = (BindingDescr) b;
                expression = bind.getVariable() + (bind.isUnification() ? " := " : " : ") + bind.getExpression();
            } else if ( b instanceof ExprConstraintDescr ) {
                ExprConstraintDescr descr = (ExprConstraintDescr) b;
                expression = descr.getExpression();
                isPositional = descr.getType() == ExprConstraintDescr.Type.POSITIONAL;
            } else {
                expression = b.getText();
            }


            ConstraintConnectiveDescr result = parseExpression( context,
                    patternDescr,
                    b,
                    expression );

            boolean isImperfect = ChanceObjectTypeNode.isImperfect(pattern.getObjectType()) || analyzeConstraintConnective( result, context, pattern );

            if ( isImperfect ) {
                hasImperfectConstraint = true;
                if ( ! isPositional && result != null ) {
                    rootConstraints.add( result );

                    int index = constraints.indexOf( b );
                    int k = index;
                    impFlags.put( k, true );
                    posFlags.put( k, false );

                    constraints.remove( index );
                    for ( BaseDescr sub : expand( result ) ) {
                        constraints.add( index, sub );
                        ++k;
                        impFlags.put( k, true );
                        posFlags.put( k, false );
                    }
                }
            } else {
                int index = constraints.indexOf( b );
                impFlags.put( index, false );

                rootConstraints.add( result );
                if (! isPositional) {
                    constraints.remove( index );
                    constraints.add( index, result );
                } else {
                    if ( result.getDescrs().get( 0 ) instanceof BindingDescr ) {
                        constraints.remove( index );
                        constraints.add( index, result );
                    }
                }

                if ( ! isPositional ) {
                    posFlags.put( index, false );
                } else {
                    posFlags.put( index, true );
                }
            }

        }

        // Add the pattern-level "and"
        if ( hasImperfectConstraint ) {
            ConstraintConnectiveDescr root = new ConstraintConnectiveDescr( ConnectiveType.AND );
            // mock "isA" to increase cardinality by 1
            root.addDescr( new RelationalExprDescr( "isA",
                    false,
                    null,
                    new AtomicExprDescr( "this" ),
                    new AtomicExprDescr( patternDescr.getObjectType() ) ) );

            for ( BaseDescr rootChild : rootConstraints ) {
                root.addDescr( rootChild );
            }
            if ( patternDescr.getAnnotation( Imperfect.class.getSimpleName() ) != null ) {
                root.addAnnotation( patternDescr.getAnnotation( Imperfect.class.getSimpleName() ) );
            }
            constraints.add( root );
            impFlags.put( constraints.size() - 1, true );
            posFlags.put( constraints.size() - 1, false );
        }


        int index = 0;
        for ( BaseDescr b : patternDescr.getDescrs() ) {
            boolean isPositional = posFlags.get( index );

                        
            if ( b instanceof BindingDescr ) {
                // it is just a bind, so build it
                buildRuleBindings( context,
                        patternDescr,
                        pattern,
                        (BindingDescr) b );
            } else if ( b instanceof ConstraintConnectiveDescr ) {
                if ( impFlags.get( index ) == true ) {
                    build(context,
                            patternDescr,
                            pattern,
                            (ConstraintConnectiveDescr) b);
                } else {

                    ConstraintConnectiveDescr result = (ConstraintConnectiveDescr) b;
                    if ( result.getDescrs().size() == 1 && result.getDescrs().get( 0 ) instanceof BindingDescr ) {
                        // it is just a bind, so build it
                        buildRuleBindings( context,
                                patternDescr,
                                pattern,
                                (BindingDescr) result.getDescrs().get( 0 ) );
                    } else {


                        super.build(context,
                                patternDescr,
                                pattern,
                                (ConstraintConnectiveDescr) b,
                                mvelCtx);
                    }
                }
            }  else if ( isPositional ) {
                processPositional(context,
                        patternDescr,
                        pattern,
                        (ExprConstraintDescr) b);
            } else {
                // need to build the actual constraint
                buildCcdDescr( context,
                        patternDescr,
                        pattern,
                        b,
                        mvelCtx);
            }

            index++;
        }

//        combineConstraints(context, pattern);
    }


    protected void processDuplicateBindings( boolean isUnification,
                                                 PatternDescr patternDescr,
                                                 Pattern pattern,
                                                 BaseDescr original,
                                                 String leftExpression,
                                                 String rightIdentifier,
                                                 RuleBuildContext context ) {
            MVELDumper.MVELDumperContext mvelCtx = new MVELDumper.MVELDumperContext().setRuleContext(context);
            if ( isUnification ) {
                String expr = leftExpression + " == " + rightIdentifier;
                ConstraintConnectiveDescr result = parseExpression( context,
                                                                    patternDescr,
                                                                    patternDescr,
                                                                    expr );
                BaseDescr constr = result.getDescrs().get( 0 );
                buildCcdDescr( context,
                        patternDescr,
                        pattern,
                        constr,
                        mvelCtx);
            } else {
                // This declaration already exists, so throw an Exception
                context.addError(new DescrBuildError(context.getParentDescr(),
                        patternDescr,
                        null,
                        "Duplicate declaration for variable '" + leftExpression + "' in the rule '" + context.getRule().getName() + "'"));
            }

        }



    private boolean analyzeConstraintConnective( BaseDescr descr, RuleBuildContext context, Pattern pattern ) {
        if ( descr instanceof ConstraintConnectiveDescr ) {
            ConstraintConnectiveDescr ccd = (ConstraintConnectiveDescr) descr;
            if ( ( (ConstraintConnectiveDescr) descr ).getAnnotation( Imperfect.class.getSimpleName() ) != null ) {
                return true;
            }
            for ( BaseDescr child : ccd.getDescrs() ) {
                if ( analyzeConstraintConnective( child, context, pattern ) ) {
                    return true;
                }
            }
        } else if ( descr instanceof RelationalExprDescr ) {
            RelationalExprDescr rel = (RelationalExprDescr) descr;
{'fraction_non_alphanumeric': 0.07867938685818415, 'fraction_numerical': 0.0009111373137528138, 'mean_word_length': 1.2705037722073498, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 44, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5715546', 'n_tokens_mistral': 4346, 'n_tokens_neox': 4030, 'n_words': 935}