// Either it's a complex expression, so do as predicate
// Or it's a Map and we have to treat it as a special case
if ( !simple || new ClassObjectType(Map.class).isAssignableFrom( pattern.getObjectType() ) ) {
Dialect dialect = context.getDialect();
MVELDialect mvelDialect = (MVELDialect) context.getDialect( "mvel" );
context.setDialect( mvelDialect );
PredicateDescr pdescr = new PredicateDescr( expr );
buildEval( context,
pattern,
pdescr,
null,
aliases );
// fall back to original dialect
context.setDialect( dialect );
continue;
}
if ( !(d instanceof RelationalExprDescr) ) {
throw new RuntimeException( "What caused this?: " + d );
}
RelationalExprDescr exprDescr = (RelationalExprDescr) d;
AtomicExprDescr rdescr = ((AtomicExprDescr) exprDescr.getRight());
String fieldName = ((AtomicExprDescr) exprDescr.getLeft()).getExpression();
String value = rdescr.getExpression().trim();
ExprBindings rightExpr = new ExprBindings();
setInputs( context,
rightExpr,
(pattern.getObjectType() instanceof ClassObjectType) ? ((ClassObjectType) pattern.getObjectType()).getClassType() : FactTemplate.class,
value );
String[] parts = fieldName.split( "\\." );
if ( parts.length == 2 ) {
if ( "this".equals( parts[0].trim() ) ) {
// it's a redundant this so trim
fieldName = parts[1];
} else if ( pattern.getDeclaration() != null && parts[0].trim().equals( pattern.getDeclaration().getIdentifier() ) ) {
// it's a redundant declaration so trim
fieldName = parts[1];
}
}
if ( fieldName.indexOf( '.' ) >= 0 || fieldName.indexOf( '[' ) >= 0 || fieldName.indexOf( '(' ) >= 0 ) {
// if left has any inputs then we need to rewrite to eval
ExprBindings leftExpr = new ExprBindings();
setInputs( context,
leftExpr,
((ClassObjectType) ((Pattern) context.getBuildStack().peek()).getObjectType()).getClassType(),
fieldName );
if ( !leftExpr.getRuleBindings().isEmpty() ) {
Dialect dialect = context.getDialect();
MVELDialect mvelDialect = (MVELDialect) context.getDialect( "mvel" );
context.setDialect( mvelDialect );
PredicateDescr pdescr = new PredicateDescr( expr );
buildEval( context,
pattern,
pdescr,
null,
aliases );
// fall back to original dialect
context.setDialect( dialect );
continue;
}
}
final InternalReadAccessor extractor = getFieldReadAccessor( context,
d,
pattern.getObjectType(),
fieldName,
null,
false );
if ( extractor == null ) {
context.getErrors().add( new DescrBuildError( context.getParentDescr(),
d,
null,
"Unable to build constraint as '" + fieldName + "' is invalid" ) );
continue;
}
String operator = relDescr.getOperator().trim();
Restriction restriction = null;
// is it a literal? Does not include enums
if ( rdescr.isLiteral() ) {
restriction = buildLiteralRestriction( context,
extractor,
new LiteralRestrictionDescr( operator,
relDescr.isNegated(),
relDescr.getParameters(),
value,
LiteralRestrictionDescr.TYPE_STRING ) ); // default type
if ( restriction == null ) {
// otherwise we just get wierd errors after this point on literals
continue;
}
} else {
// is it an enum?
int dotPos = value.lastIndexOf( '.' );
if ( dotPos >= 0 ) {
final String mainPart = value.substring( 0,
dotPos );
String lastPart = value.substring( dotPos + 1 );
try {
final Class< ? > cls = context.getDialect().getTypeResolver().resolveType( mainPart );
if ( lastPart.indexOf( '(' ) < 0 && lastPart.indexOf( '.' ) < 0 && lastPart.indexOf( '[' ) < 0 ) {
restriction = buildLiteralRestriction( context,
extractor,
new LiteralRestrictionDescr( operator,
relDescr.isNegated(),
relDescr.getParameters(),
value,
LiteralRestrictionDescr.TYPE_STRING ) ); // default type
}
} catch ( ClassNotFoundException e ) {
// do nothing as this is just probing to see if it was a class, which we now know it isn't :)
}
}
}
if ( restriction != null ) {
pattern.addConstraint( new LiteralConstraint( extractor,
(LiteralRestriction) restriction ) );
continue;
}
Declaration declr = null;
if ( value.indexOf( '(' ) < 0 && value.indexOf( '.' ) < 0 && value.indexOf( '[' ) < 0 ) {
declr = context.getDeclarationResolver().getDeclaration( context.getRule(),
value );
if ( declr == null ) {
// trying to create implicit declaration
final Pattern thisPattern = (Pattern) context.getBuildStack().peek();
declr = this.createDeclarationObject( context,
value,
thisPattern );
if ( declr == null ) {
context.getErrors().add( new DescrBuildError( context.getParentDescr(),
d,
null,
"Unable to return Declaration for identifier '" + value + "'" ) );
continue;
}
}
}
if ( declr == null ) {
parts = value.split( "\\." );
if ( parts.length == 2 ) {
if ( "this".equals( parts[0].trim() ) ) {
declr = this.createDeclarationObject( context,
parts[1].trim(),
(Pattern) context.getBuildStack().peek() );
value = parts[1].trim();
} else {
declr = context.getDeclarationResolver().getDeclaration( context.getRule(),
parts[0].trim() );
// if a declaration exists, then it may be a variable direct property access
if ( declr != null ) {
if ( declr.isPatternDeclaration() ) {
declr = this.createDeclarationObject( context,
parts[1].trim(),
declr.getPattern() );
value = parts[1].trim();
} else {
context.getErrors().add( new DescrBuildError( context.getParentDescr(),
d,
"",
"Not possible to directly access the property '" + parts[1] + "' of declaration '" + parts[0] + "' since it is not a pattern" ) );
continue;
}
}
}
}
}
if ( declr != null ) {
Target right = getRightTarget( extractor );
Target left = (declr.isPatternDeclaration() && !(Date.class.isAssignableFrom( declr.getExtractor().getExtractToClass() ) || Number.class.isAssignableFrom( declr.getExtractor().getExtractToClass() ))) ? Target.HANDLE : Target.FACT;
final Evaluator evaluator = getEvaluator( context,
d,
extractor.getValueType(),
operator,
relDescr.isNegated(),
relDescr.getParametersText(),
left,
right );
if ( evaluator == null ) {
continue;
}
restriction = new VariableRestriction( extractor,
declr,
evaluator );
if ( declr.getPattern().getObjectType().equals( new ClassObjectType( DroolsQuery.class ) ) ) {
// declaration is query argument, so allow for unification.
restriction = new UnificationRestriction( (VariableRestriction) restriction );
}
}
if ( restriction == null ) {
Dialect dialect = context.getDialect();
if ( !value.startsWith( "(" ) ) {
// it's not a traditional return value, so override the dialect
MVELDialect mvelDialect = (MVELDialect) context.getDialect( "mvel" );
context.setDialect( mvelDialect );
}
// execute it as a return value
restriction = buildRestriction( context,