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());
}
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));
}
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;
}
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);
}
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);
}
}
Aggregations