Search in sources :

Example 16 with DescrBuildError

use of org.drools.compiler.compiler.DescrBuildError in project drools by kiegroup.

the class QueryElementBuilder method build.

@SuppressWarnings("unchecked")
public RuleConditionElement build(RuleBuildContext context, BaseDescr descr, QueryImpl query) {
    PatternDescr patternDescr = (PatternDescr) descr;
    Declaration[] params = query.getParameters();
    List<BaseDescr> args = (List<BaseDescr>) patternDescr.getDescrs();
    List<Declaration> requiredDeclarations = new ArrayList<Declaration>();
    ObjectType argsObjectType = ClassObjectType.ObjectArray_ObjectType;
    InternalReadAccessor arrayReader = new SelfReferenceClassFieldReader(Object[].class);
    Pattern pattern = new Pattern(context.getNextPatternId(), 0, argsObjectType, null);
    if (!StringUtils.isEmpty(patternDescr.getIdentifier())) {
        if (query.isAbductive()) {
            Declaration declr = context.getDeclarationResolver().getDeclaration(patternDescr.getIdentifier());
            if (declr != null && !patternDescr.isUnification()) {
                context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Duplicate declaration " + patternDescr.getIdentifier() + ", unable to bind abducted value"));
            }
        } else {
            context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Query binding is not supported by non-abductive queries : " + patternDescr.getIdentifier()));
        }
    }
    boolean addAbductiveReturnArgument = query.isAbductive() && !StringUtils.isEmpty(patternDescr.getIdentifier()) && args.size() < params.length;
    if (addAbductiveReturnArgument) {
        ExprConstraintDescr extraDescr = new ExprConstraintDescr(patternDescr.getIdentifier());
        extraDescr.setPosition(patternDescr.getConstraint().getDescrs().size());
        extraDescr.setType(ExprConstraintDescr.Type.POSITIONAL);
        args.add(extraDescr);
    }
    QueryArgument[] arguments = new QueryArgument[params.length];
    // Deal with the constraints, both positional and bindings
    for (BaseDescr base : args) {
        String expression = null;
        boolean isPositional = false;
        boolean isBinding = false;
        BindingDescr bind = null;
        ConstraintConnectiveDescr result = null;
        if (base instanceof BindingDescr) {
            bind = (BindingDescr) base;
            expression = bind.getVariable() + (bind.isUnification() ? " := " : " : ") + bind.getExpression();
            isBinding = true;
        } else {
            if (base instanceof ExprConstraintDescr) {
                ExprConstraintDescr ecd = (ExprConstraintDescr) base;
                expression = ecd.getExpression();
                isPositional = ecd.getType() == ExprConstraintDescr.Type.POSITIONAL;
            } else {
                expression = base.getText();
            }
            result = parseExpression(context, patternDescr, expression);
            if (result == null) {
                // error, can't parse expression.
                context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Unable to parse constraint: \n" + expression));
                continue;
            }
            isBinding = result.getDescrs().size() == 1 && result.getDescrs().get(0) instanceof BindingDescr;
            if (isBinding) {
                bind = (BindingDescr) result.getDescrs().get(0);
            }
        }
        if ((!isPositional) && (!isBinding)) {
            // error, can't have non binding slots.
            context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Query's must use positional or bindings, not field constraints:\n" + expression));
        } else if (isPositional && isBinding) {
            // error, can't have positional binding slots.
            context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Query's can't use positional bindings:\n" + expression));
        } else if (isPositional) {
            processPositional(context, query, params, arguments, requiredDeclarations, arrayReader, pattern, base, expression, result);
        } else {
            // it is binding
            processBinding(context, descr, params, arguments, requiredDeclarations, arrayReader, pattern, bind);
        }
    }
    List<Integer> varIndexList = new ArrayList<Integer>();
    for (int i = 0; i < arguments.length; i++) {
        if (!(arguments[i] instanceof QueryArgument.Declr)) {
            if (arguments[i] instanceof QueryArgument.Var) {
                varIndexList.add(i);
            }
            continue;
        }
        Class actual = ((QueryArgument.Declr) arguments[i]).getArgumentClass();
        Declaration formalArgument = query.getParameters()[i];
        Class formal = formalArgument.getDeclarationClass();
        // input argument require a broader type, while output types require a narrower type, so we check for both.
        if (!ClassUtils.isTypeCompatibleWithArgumentType(actual, formal) && !ClassUtils.isTypeCompatibleWithArgumentType(formal, actual)) {
            context.addError(new DescrBuildError(context.getParentDescr(), descr, null, "Query is being invoked with known argument of type " + actual + " at position " + i + ", but the expected query argument is of type " + formal));
        }
    }
    return new QueryElement(pattern, query.getName(), arguments, toIntArray(varIndexList), requiredDeclarations.toArray(new Declaration[requiredDeclarations.size()]), !patternDescr.isQuery(), query.isAbductive());
}
Also used : BindingDescr(org.drools.compiler.lang.descr.BindingDescr) QueryArgument(org.drools.core.rule.QueryArgument) PatternDescr(org.drools.compiler.lang.descr.PatternDescr) ArrayList(java.util.ArrayList) QueryElement(org.drools.core.rule.QueryElement) ClassObjectType(org.drools.core.base.ClassObjectType) ObjectType(org.drools.core.spi.ObjectType) InternalReadAccessor(org.drools.core.spi.InternalReadAccessor) ArrayList(java.util.ArrayList) List(java.util.List) Declaration(org.drools.core.rule.Declaration) ConstraintConnectiveDescr(org.drools.compiler.lang.descr.ConstraintConnectiveDescr) Pattern(org.drools.core.rule.Pattern) DescrBuildError(org.drools.compiler.compiler.DescrBuildError) SelfReferenceClassFieldReader(org.drools.core.base.extractors.SelfReferenceClassFieldReader) BaseDescr(org.drools.compiler.lang.descr.BaseDescr) ExprConstraintDescr(org.drools.compiler.lang.descr.ExprConstraintDescr)

Example 17 with DescrBuildError

use of org.drools.compiler.compiler.DescrBuildError in project drools by kiegroup.

the class DialectUtil method rewriteInterfacePoint.

@SuppressWarnings("unchecked")
private static void rewriteInterfacePoint(final RuleBuildContext context, final String originalCode, final StringBuilder consequence, final JavaInterfacePointsDescr ep) {
    // rewriting it for proper exitPoints access
    consequence.append("drools.get");
    if (ep.getType() == JavaBlockDescr.BlockType.EXIT) {
        consequence.append("ExitPoint( ");
    } else if (ep.getType() == JavaBlockDescr.BlockType.ENTRY) {
        consequence.append("EntryPoint( ");
    } else if (ep.getType() == JavaBlockDescr.BlockType.CHANNEL) {
        consequence.append("Channel( ");
    } else {
        context.addError(new DescrBuildError(context.getParentDescr(), context.getRuleDescr(), ep, "Unable to rewrite code block: " + ep + "\n"));
        return;
    }
    consequence.append(ep.getId());
    consequence.append(" )");
    // the following is a hack to preserve line breaks.
    String originalBlock = originalCode.substring(ep.getStart() - 1, ep.getEnd());
    int end = originalBlock.indexOf("]");
    addLineBreaks(consequence, originalBlock.substring(0, end));
}
Also used : DescrBuildError(org.drools.compiler.compiler.DescrBuildError)

Example 18 with DescrBuildError

use of org.drools.compiler.compiler.DescrBuildError in project drools by kiegroup.

the class DialectUtil method rewriteDescr.

private static boolean rewriteDescr(final RuleBuildContext context, final String originalCode, final MVELDialect mvel, final StringBuilder consequence, final JavaBlockDescr d, final BoundIdentifiers bindings, final Map<String, Declaration> decls) {
    if (d.getEnd() == 0) {
        // do nothing, it was incorrectly parsed, but this error should be picked up else where
        return false;
    }
    boolean typeSafety = context.isTypesafe();
    // we have to analyse in dynamic mode for now, as we cannot safely determine all input vars
    context.setTypesafe(false);
    Map<String, Class<?>> localTypes = d.getInputs();
    if (d.getInScopeLocalVars() != null && !d.getInScopeLocalVars().isEmpty()) {
        localTypes = new HashMap<String, Class<?>>(d.getInputs() != null ? d.getInputs() : Collections.EMPTY_MAP);
        for (JavaLocalDeclarationDescr local : d.getInScopeLocalVars()) {
            // these are variables declared in the code itself that are in the scope for this expression
            try {
                Class<?> type = context.getDialect("java").getPackageRegistry().getTypeResolver().resolveType(local.getRawType());
                for (IdentifierDescr id : local.getIdentifiers()) {
                    localTypes.put(id.getIdentifier(), type);
                }
            } catch (ClassNotFoundException e) {
                context.addError(new DescrBuildError(context.getRuleDescr(), context.getParentDescr(), null, "Unable to resolve type " + local.getRawType() + ":\n" + e.getMessage()));
            }
        }
    }
    MVELAnalysisResult mvelAnalysis = (MVELAnalysisResult) mvel.analyzeBlock(context, d.getTargetExpression(), bindings, localTypes, "drools", KnowledgeHelper.class);
    context.setTypesafe(typeSafety);
    if (mvelAnalysis == null) {
        // something bad happened, issue already logged in errors
        return false;
    }
    Class ret = mvelAnalysis.getReturnType();
    if (ret == null) {
        // not possible to evaluate expression return value
        context.addError(new DescrBuildError(context.getParentDescr(), context.getRuleDescr(), originalCode, "Unable to determine the resulting type of the expression: " + d.getTargetExpression() + "\n"));
        return false;
    }
    // adding modify expression
    String retString = ClassUtils.canonicalName(ret);
    String declrString;
    if (d.getTargetExpression().charAt(0) == '(') {
        declrString = d.getTargetExpression().substring(1, d.getTargetExpression().length() - 1).trim();
    } else {
        declrString = d.getTargetExpression();
    }
    String obj = declrString;
    Declaration declr = decls.get(declrString);
    consequence.append("{ ");
    if (declr == null) {
        obj = "__obj__";
        consequence.append(retString);
        consequence.append(" ");
        consequence.append(obj);
        consequence.append(" = ");
        consequence.append(d.getTargetExpression());
        consequence.append("; ");
    }
    if (declr == null || declr.isInternalFact()) {
        consequence.append("org.kie.api.runtime.rule.FactHandle ");
        consequence.append(obj);
        consequence.append("__Handle2__ = drools.getFactHandle(");
        consequence.append(obj);
        consequence.append(");");
    }
    // the following is a hack to preserve line breaks.
    String originalBlock = originalCode.substring(d.getStart() - 1, d.getEnd());
    switch(d.getType()) {
        case MODIFY:
            rewriteModifyDescr(context, d, originalBlock, consequence, declr, obj);
            break;
        case UPDATE:
            rewriteUpdateDescr(context, d, consequence, declr, obj);
            break;
        case DELETE:
            rewriteDeleteDescr(context, d, consequence, declr, obj);
            break;
    }
    return declr != null;
}
Also used : DescrBuildError(org.drools.compiler.compiler.DescrBuildError) MVELAnalysisResult(org.drools.compiler.rule.builder.dialect.mvel.MVELAnalysisResult) JavaLocalDeclarationDescr(org.drools.compiler.rule.builder.dialect.java.parser.JavaLocalDeclarationDescr) KnowledgeHelper(org.drools.core.spi.KnowledgeHelper) TypeDeclaration(org.drools.core.rule.TypeDeclaration) Declaration(org.drools.core.rule.Declaration) IdentifierDescr(org.drools.compiler.rule.builder.dialect.java.parser.JavaLocalDeclarationDescr.IdentifierDescr)

Example 19 with DescrBuildError

use of org.drools.compiler.compiler.DescrBuildError in project drools by kiegroup.

the class ParserTest method testErrorLineNumbers.

@Test
public void testErrorLineNumbers() throws Exception {
    // this test aims to test semantic errors
    // parser errors are another test case
    final KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    kbuilder.add(ResourceFactory.newClassPathResource("errors_in_rule.drl", getClass()), ResourceType.DRL);
    final KnowledgeBuilderError[] errors = kbuilder.getErrors().toArray(new KnowledgeBuilderError[0]);
    assertEquals(3, errors.length);
    final DescrBuildError stiltonError = (DescrBuildError) errors[0];
    assertTrue(stiltonError.getMessage().contains("Stilton"));
    assertNotNull(stiltonError.getDescr());
    assertTrue(stiltonError.getLine() != -1);
    // check that its getting it from the ruleDescr
    assertEquals(stiltonError.getLine(), stiltonError.getDescr().getLine());
    // check the absolute error line number (there are more).
    assertEquals(26, stiltonError.getLine());
    final DescrBuildError poisonError = (DescrBuildError) errors[1];
    assertTrue(poisonError.getMessage().contains("Poison"));
    assertEquals(28, poisonError.getLine());
    final KnowledgeBuilderConfigurationImpl cfg = new KnowledgeBuilderConfigurationImpl();
    final JavaDialectConfiguration javaConf = (JavaDialectConfiguration) cfg.getDialectConfiguration("java");
    switch(javaConf.getCompiler()) {
        case NATIVE:
            assertTrue(errors[2].getMessage().contains("illegal"));
            break;
        case ECLIPSE:
            assertTrue(errors[2].getMessage().contains("add"));
            break;
        case JANINO:
            assertTrue(errors[2].getMessage().contains("Unexpected"));
            break;
        default:
            fail("Unknown compiler used");
    }
    // now check the RHS, not being too specific yet, as long as it has the
    // rules line number, not zero
    final DescrBuildError rhsError = (DescrBuildError) errors[2];
    assertTrue(rhsError.getLine() >= 23 && rhsError.getLine() <= 32);
}
Also used : KnowledgeBuilderError(org.kie.internal.builder.KnowledgeBuilderError) KnowledgeBuilder(org.kie.internal.builder.KnowledgeBuilder) DescrBuildError(org.drools.compiler.compiler.DescrBuildError) KnowledgeBuilderConfigurationImpl(org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl) JavaDialectConfiguration(org.drools.compiler.rule.builder.dialect.java.JavaDialectConfiguration) Test(org.junit.Test)

Example 20 with DescrBuildError

use of org.drools.compiler.compiler.DescrBuildError in project drools by kiegroup.

the class MVELAccumulateBuilder method build.

@SuppressWarnings("unchecked")
public RuleConditionElement build(final RuleBuildContext context, final BaseDescr descr, final Pattern prefixPattern) {
    boolean typesafe = context.isTypesafe();
    try {
        final AccumulateDescr accumDescr = (AccumulateDescr) descr;
        if (!accumDescr.hasValidInput()) {
            return null;
        }
        final RuleConditionBuilder builder = (RuleConditionBuilder) context.getDialect().getBuilder(accumDescr.getInput().getClass());
        // create source CE
        final RuleConditionElement source = builder.build(context, accumDescr.getInput());
        if (source == null) {
            return null;
        }
        MVELDialect dialect = (MVELDialect) context.getDialect();
        Map<String, Declaration> decls = context.getDeclarationResolver().getDeclarations(context.getRule());
        Map<String, Declaration> sourceOuterDeclr = source.getOuterDeclarations();
        Map<String, Class<?>> declarationClasses = DeclarationScopeResolver.getDeclarationClasses(decls);
        declarationClasses.putAll(DeclarationScopeResolver.getDeclarationClasses(sourceOuterDeclr));
        BoundIdentifiers boundIds = new BoundIdentifiers(declarationClasses, context);
        final boolean readLocalsFromTuple = PackageBuilderUtil.isReadLocalsFromTuple(context, accumDescr, source);
        Accumulator[] accumulators;
        if (accumDescr.isExternalFunction()) {
            // uses accumulate functions
            accumulators = buildExternalFunctions(context, accumDescr, dialect, decls, sourceOuterDeclr, boundIds, readLocalsFromTuple);
        } else {
            // it is a custom accumulate
            accumulators = buildCustomAccumulate(context, accumDescr, dialect, decls, sourceOuterDeclr, boundIds, readLocalsFromTuple);
        }
        List<Declaration> requiredDeclarations = new ArrayList<Declaration>();
        for (Accumulator acc : accumulators) {
            MvelAccumulator mvelAcc = (MvelAccumulator) acc;
            Collections.addAll(requiredDeclarations, mvelAcc.getRequiredDeclarations());
        }
        MVELDialectRuntimeData data = (MVELDialectRuntimeData) context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel");
        Accumulate accumulate;
        if (accumDescr.isMultiFunction()) {
            accumulate = new MultiAccumulate(source, requiredDeclarations.toArray(new Declaration[requiredDeclarations.size()]), accumulators);
            int index = 0;
            for (Accumulator accumulator : accumulators) {
                data.addCompileable(((MultiAccumulate) accumulate).new Wirer(index++), (MVELCompileable) accumulator);
                ((MVELCompileable) accumulator).compile(data, context.getRule());
            }
        } else {
            accumulate = new SingleAccumulate(source, requiredDeclarations.toArray(new Declaration[requiredDeclarations.size()]), accumulators[0]);
            data.addCompileable(((SingleAccumulate) accumulate).new Wirer(), (MVELCompileable) accumulators[0]);
            ((MVELCompileable) accumulators[0]).compile(data, context.getRule());
        }
        return accumulate;
    } catch (Exception e) {
        DialectUtil.copyErrorLocation(e, descr);
        context.addError(new DescrBuildError(context.getParentDescr(), descr, e, "Unable to build expression for 'accumulate' : " + e.getMessage()));
        return null;
    } finally {
        context.setTypesafe(typesafe);
    }
}
Also used : MVELAccumulator(org.drools.core.base.mvel.MVELAccumulator) Accumulator(org.drools.core.spi.Accumulator) MvelAccumulator(org.drools.core.spi.MvelAccumulator) MVELCompileable(org.drools.core.base.mvel.MVELCompileable) ArrayList(java.util.ArrayList) AccumulateDescr(org.drools.compiler.lang.descr.AccumulateDescr) MultiAccumulate(org.drools.core.rule.MultiAccumulate) SingleAccumulate(org.drools.core.rule.SingleAccumulate) Accumulate(org.drools.core.rule.Accumulate) MVELDialectRuntimeData(org.drools.core.rule.MVELDialectRuntimeData) Declaration(org.drools.core.rule.Declaration) MultiAccumulate(org.drools.core.rule.MultiAccumulate) RuleConditionBuilder(org.drools.compiler.rule.builder.RuleConditionBuilder) RuleConditionElement(org.drools.core.rule.RuleConditionElement) SingleAccumulate(org.drools.core.rule.SingleAccumulate) MutableTypeConstraint(org.drools.core.rule.MutableTypeConstraint) MvelConstraint(org.drools.core.rule.constraint.MvelConstraint) Constraint(org.drools.core.spi.Constraint) BoundIdentifiers(org.drools.compiler.compiler.BoundIdentifiers) DescrBuildError(org.drools.compiler.compiler.DescrBuildError) MvelAccumulator(org.drools.core.spi.MvelAccumulator)

Aggregations

DescrBuildError (org.drools.compiler.compiler.DescrBuildError)29 Declaration (org.drools.core.rule.Declaration)16 MVELCompilationUnit (org.drools.core.base.mvel.MVELCompilationUnit)10 MVELDialectRuntimeData (org.drools.core.rule.MVELDialectRuntimeData)8 AnalysisResult (org.drools.compiler.compiler.AnalysisResult)7 BoundIdentifiers (org.drools.compiler.compiler.BoundIdentifiers)7 Pattern (org.drools.core.rule.Pattern)6 MvelConstraint (org.drools.core.rule.constraint.MvelConstraint)5 ArrayElementReader (org.drools.core.base.extractors.ArrayElementReader)4 MutableTypeConstraint (org.drools.core.rule.MutableTypeConstraint)4 InternalReadAccessor (org.drools.core.spi.InternalReadAccessor)4 ArrayList (java.util.ArrayList)3 BaseDescr (org.drools.compiler.lang.descr.BaseDescr)3 ConstraintConnectiveDescr (org.drools.compiler.lang.descr.ConstraintConnectiveDescr)3 SelfReferenceClassFieldReader (org.drools.core.base.extractors.SelfReferenceClassFieldReader)3 QueryArgument (org.drools.core.rule.QueryArgument)3 Constraint (org.drools.core.spi.Constraint)3 KnowledgeHelper (org.drools.core.spi.KnowledgeHelper)3 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2