The problem is not the loop in isEqualMore. I think the problem is caused by MVEL not handling the signature (Ann...) correctly.
@Mario: should MVEL be able to deal with such a function call? -W On 07/03/2013, Bojan Janisch <[email protected]> wrote: > I've tested all 4 cases. It is strange that each Rule fired exactly one > time, > directly before the exception occurs. Here the rules, I've built them > exactly > for this problem. > ============================================ > Test 1(isEqualMore): > rule "Test Experiment 1" > no-loop > when > $a1:ODMAnswer() > > $a2:ODMAnswer( > !isEqual($a1,$a2), > comesAfter($a1,$a2,50)) > > $a3:ODMAnswer( > comesAfter($a2,$a3,20), > !isEqualMore($a1,$a2,$a3)) > then > System.out.println("Test 1 works"); > end > > Result: > Same Runtime exception > ============================================ > Test 2(isEqualThree): > rule "Test Experiment 2" > no-loop > when > $a1:ODMAnswer() > > $a2:ODMAnswer( > !isEqual($a1,$a2), > comesAfter($a1,$a2,50)) > > $a3:ODMAnswer( > comesAfter($a2,$a3,20), > !isEqualThree($a1,$a2,$a3)) > then > System.out.println("Test 2 works"); > end > Result: > Works perfect without errors. > ============================================ > Test 3(isEqualMore): > rule "Test Experiment 3" > no-loop > when > $a1:ODMAnswer() > > $a2:ODMAnswer( > !isEqual($a1,$a2), > comesAfter($a1,$a2,5)) > > ($a3:ODMAnswer( > comesAfter($a2,$a3,5)) and > eval(!isEqualMore($a1,$a2,$a3))) > then > System.out.println("Test 3 works"); > end > Result: > Works also without errors (I'm surprised). > ============================================ > Test 4(isEqualThree): > rule "Test Experiment 4" > no-loop > when > $a1:ODMAnswer() > > $a2:ODMAnswer( > !isEqual($a1,$a2), > comesAfter($a1,$a2,5)) > > ($a3:ODMAnswer( > comesAfter($a2,$a3,5)) and > eval(!isEqualThree($a1,$a2,$a3))) > then > System.out.println("Test 4 works"); > end > Result: > Works perfect, but seems to get more matches > than the 3. experiment. > ============================================ > Fazit: > > In my eyes there seems to be a problem using a loop in a constraint. > Even if I use different names (see Test 2), I'm still getting the > runtime exception. As bonus test-case I've tried using Test 3 and > overloading the function, rather than using a different function name, > but this also failed. > > Seems that I have to use eval() and different names if I want to compare > multiple named entities, though I still don't know why. Maybe the isEqual > call in the loop is calling itself and generating an out of bounds exception > at the last array entity. > > Thank you wolfgang. > > JB > ----- Ursprüngliche Mail ----- > Von: "Wolfgang Laun" <[email protected]> > An: "Rules Users List" <[email protected]> > Gesendet: Donnerstag, 7. März 2013 13:36:12 > Betreff: Re: [rules-users] Cannot invoke method because > of ArrayIndexOutOfBoundsException > > You have lost me - I'm not sure anymore what works and what doesn't. > > Please check or rewrite, using the names > isEqualMore(Annotation... annos) > isEqualThree(Annotation a1, Annotation a2, Annotation a3) > > 1) not $a5:ODMAnswer(..., ! isEqualX($a3,$a4,$a5) ) > does not work for X==More and > does not work for X==Three > > 2) not( $a5:ODMAnswer(...) and eval( ! isEqualX($a3,$a4,$a5) ) > works for X==More and > works for X==Three > > -W > > > > > On 07/03/2013, Bojan Janisch <[email protected]> wrote: >>> Experiment 1 >>> Please write isEqualThree for 3 Annotation arguments and use this, >>> just to make sure that these Problems are caused by Drools. (Do NOT >>> rely on overloading, use another name.) >> >> I've created an isEqualThree function >> >> public static boolean isEqualThree(Annotation a, Annotation b, Annotation >> c){ >> if(isEqual(a,b) || isEqual(b,c) || isEqual(a,c)){ >> return true; >> } >> return false; >> } >> >> By the way, it works also with overloading, I've never had problems with >> overloading in Drools. And I've tested also with different names, the >> problem >> remains, even using different function names. >> >>> Experiment 2 >>> Using the isEqual as it is now, rewrite the last pattern as: >>> >>> not ( $a5:ODMAnswer( >>> isInAnnotation($a1,$a5), >>> isBigger($a3,$a5) ) >>> and >>> eval( ! isEqual($a3,$a4,$a5) ) >>> ) >> >> Your condition works without problems using the isEqualThree function, it >> works >> also if I overload the function. It also works if I put the isEqual >> condition out >> of the eval, into the object constraints. But if I want to use my primary >> idea, using >> different names, >> >> public static boolean isEqualMore(Annotation... a) >> >> I still get the same error from the isEqualMore function. >> >> java.lang.RuntimeException: cannot invoke method: isEqualMore >> at >> de.fraunhofer.scai.bio.uima.core.deploy.StatusCallbackListenerImpl.entityProcessComplete(StatusCallbackListenerImpl.java:151) >> at >> org.apache.uima.collection.impl.cpm.engine.CPMThreadGroup.notifyListener(CPMThreadGroup.java:103) >> at >> org.apache.uima.collection.impl.cpm.engine.CPMThreadGroup.uncaughtException(CPMThreadGroup.java:86) >> at java.lang.Thread.dispatchUncaughtException(Thread.java:1888) >> Caused by: java.lang.ArrayIndexOutOfBoundsException: 3 >> at >> org.mvel2.optimizers.impl.refl.nodes.MethodAccessor.executeAll(MethodAccessor.java:149) >> at >> org.mvel2.optimizers.impl.refl.nodes.MethodAccessor.getValue(MethodAccessor.java:48) >> at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:108) >> at >> org.mvel2.compiler.ExecutableAccessor.getValue(ExecutableAccessor.java:38) >> at org.mvel2.ast.Negation.getReducedValueAccelerated(Negation.java:48) >> at org.mvel2.MVELRuntime.execute(MVELRuntime.java:85) >> at >> org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:123) >> at >> org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:116) >> at org.mvel2.MVEL.executeExpression(MVEL.java:930) >> at >> org.drools.rule.constraint.MvelConditionEvaluator.evaluate(MvelConditionEvaluator.java:70) >> at >> org.drools.rule.constraint.MvelConditionEvaluator.ensureBranchEvaluation(MvelConditionEvaluator.java:113) >> at >> org.drools.rule.constraint.MvelConditionEvaluator.ensureCompleteEvaluation(MvelConditionEvaluator.java:106) >> at >> org.drools.rule.constraint.MvelConditionEvaluator.ensureCompleteEvaluation(MvelConditionEvaluator.java:90) >> at >> org.drools.rule.constraint.MvelConditionEvaluator.getAnalyzedCondition(MvelConditionEvaluator.java:82) >> at >> org.drools.rule.constraint.MvelConstraint.executeJitting(MvelConstraint.java:214) >> at >> org.drools.rule.constraint.MvelConstraint.access$000(MvelConstraint.java:41) >> at >> org.drools.rule.constraint.MvelConstraint$1.run(MvelConstraint.java:201) >> at >> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) >> at >> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) >> at java.lang.Thread.run(Thread.java:679) >> >> JB >> >> ----- Ursprüngliche Mail ----- >> Von: "Wolfgang Laun" <[email protected]> >> An: "Rules Users List" <[email protected]> >> Gesendet: Donnerstag, 7. März 2013 06:46:29 >> Betreff: Re: [rules-users] Cannot invoke method because >> of ArrayIndexOutOfBoundsException >> >> On 06/03/2013, Bojan Janisch <[email protected]> wrote: >>> But that's exactly what java is doing if you say the Arguments are >>> method(X... xs). >>> Java is then generating an array of the type you set and you can work >>> with >>> xs like an >>> normal array. >> >> Yes, Java, but. >> >>> By the way, seems I get this Error >>> >>> Unable to Analyse Expression isEqual(new Annotation[]{$a3,$a4,$a5}) >>> [Error: could not instantiate class] >>> [Near : {... isEqual(new Annotation[]{$a3,$a4,$a5}) ....}] >>> ^ >>> [Line: 129, Column: 8] >> >> Suspicious, may have to raise a JIRA. >> >> Experiment 1 >> Please write isEqualThree for 3 Annotation arguments and use this, >> just to make sure that these Problems are caused by Drools. (Do NOT >> rely on overloading, use another name.) >> >> Experiment 2 >> Using the isEqual as it is now, rewrite the last pattern as: >> >> not ( $a5:ODMAnswer( >> isInAnnotation($a1,$a5), >> isBigger($a3,$a5) ) >> and >> eval( ! isEqual($a3,$a4,$a5) ) >> ) >> >> >> -W >> >>> >>> >>> The changed method is: >>> >>> public static boolean isEqual(Annotation[] a){ >>> ArrayList<Annotation> outLoop = new >>> ArrayList<Annotation>(Arrays.asList(a)); >>> ArrayList<Annotation> inLoop = new >>> ArrayList<Annotation>(Arrays.asList(a)); >>> >>> for (Annotation anno1 : outLoop) { >>> inLoop.remove(anno1); >>> for (Annotation anno2 : inLoop) { >>> if(isEqual(anno1,anno2)){ >>> return true; >>> } >>> } >>> } >>> >>> return false; >>> } >>> >>> ----- Ursprüngliche Mail ----- >>> Von: "Wolfgang Laun" <[email protected]> >>> An: "Rules Users List" <[email protected]> >>> Gesendet: Mittwoch, 6. März 2013 17:11:43 >>> Betreff: Re: [rules-users] Cannot invoke method because >>> of ArrayIndexOutOfBoundsException >>> >>> I wouldn't use (X... xs) in this context. >>> >>> Try the simple modification of isEqual( Annotation[] annos ) and >>> call it with isEqual( new Annotation[]{$a3,$a4,$a5}) >>> and we'll see what we'll see. >>> >>> -W >>> >>> >>> On 06/03/2013, Bojan Janisch <[email protected]> wrote: >>>> Like you wish wolfgang. The complete Rule is: >>>> >>>> rule "Generate Finding_ConceptId" >>>> no-loop >>>> when >>>> $a1:ODMAnswer( >>>> q1:QuestionId, >>>> q1.toLowerCase.contains("diagnose") || >>>> q1.toLowerCase.contains("indication"), >>>> q1.toLowerCase.contains("sections"), >>>> a1_begin:begin, >>>> label1:ResponseAttribute) >>>> >>>> $a2:ODMAnswer( >>>> ResponseAttribute.contains(label1), >>>> QuestionId.contains("sectionheader"), >>>> comesBefore($a1,$a2)); >>>> >>>> $a3:ODMAnswer( >>>> q3:QuestionId, >>>> !q3.contains("finding.conceptId"), >>>> !q3.contains("itemGroup"), >>>> !q3.contains("section"), >>>> a3_begin:begin, >>>> a3_end:end, >>>> label2:ResponseAttribute, >>>> isInAnnotation($a1,$a3)) >>>> >>>> $a4:ODMAnswer( >>>> q4:QuestionId.contains("finding.conceptId"), >>>> a4_begin:begin, >>>> comesAfter($a2,$a4), >>>> isBetween($a2,$a3,$a4), >>>> isInAnnotation($a1,$a4)) >>>> >>>> not $a5:ODMAnswer( >>>> isInAnnotation($a1,$a5), >>>> isBigger($a3,$a5), >>>> !isEqual($a3,$a4,$a5)) >>>> then >>>> String questionId = "finding.conceptId"; >>>> String attribute = label1 +" "+ label2; >>>> int begin = a4_begin; >>>> int ende = a3_end; >>>> boolean addToIndexes = true; >>>> >>>> >>>> insert(annotate(aJCas, questionId, attribute, begin, ende, >>>> addToIndexes)); >>>> end >>>> >>>> The functions are in a seperate FactChecker class, because the >>>> "incode-comparison" >>>> was too much of a chaos. So I wrote functions which explains themselves >>>> what >>>> they do: >>>> ================================================================== >>>> public static boolean isInAnnotation(Annotation a, Annotation b){ >>>> if(isNull(a,b)){ >>>> return false; >>>> } >>>> if(b.getBegin() > a.getBegin() && b.getEnd() < a.getEnd()){ >>>> return true; >>>> } >>>> if(a.getBegin() > b.getBegin() && a.getEnd() < b.getEnd()){ >>>> return true; >>>> } >>>> return false; >>>> } >>>> ================================================================== >>>> public static boolean isInAnnotation(Annotation... a){ >>>> for (int i = 0; i < a.length; i++){ >>>> if(i+1 == a.length){ >>>> return false; >>>> } >>>> if(isInAnnotation(a[i], a[i+1])){ >>>> return true; >>>> } >>>> } >>>> >>>> return false; >>>> } >>>> ================================================================== >>>> public static boolean comesBefore(Annotation a, Annotation b){ >>>> if(isNull(a,b)){ >>>> return false; >>>> } >>>> if(b.getEnd() <= a.getBegin()){ >>>> return true; >>>> } >>>> >>>> return false; >>>> } >>>> ================================================================== >>>> public static boolean comesAfter(Annotation a, Annotation b){ >>>> if(isNull(a,b)){ >>>> return false; >>>> } >>>> if(a.getEnd() <= b.getBegin()){ >>>> return true; >>>> } >>>> >>>> return false; >>>> } >>>> ================================================================== >>>> public static boolean isEqual(Annotation a, Annotation b){ >>>> if(isNull(a,b)){ >>>> return false; >>>> } >>>> if(a.equals(b)){ >>>> return true; >>>> } >>>> >>>> return false; >>>> } >>>> ================================================================== >>>> public static boolean isEqual(Annotation... a){ >>>> ArrayList<Annotation> outLoop = new >>>> ArrayList<Annotation>(Arrays.asList(a)); >>>> ArrayList<Annotation> inLoop = new >>>> ArrayList<Annotation>(Arrays.asList(a)); >>>> >>>> for (Annotation anno1 : outLoop) { >>>> if(anno1 == null){ >>>> >>>> } >>>> inLoop.remove(anno1); >>>> for (Annotation anno2 : inLoop) { >>>> if(isEqual(anno1,anno2)){ >>>> return true; >>>> } >>>> } >>>> } >>>> >>>> return false; >>>> } >>>> ================================================================== >>>> public static boolean isNull(Annotation... a){ >>>> for (Annotation annotation : a) { >>>> if(annotation == null){ >>>> return true; >>>> } >>>> } >>>> >>>> return false; >>>> } >>>> ================================================================== >>>> public static boolean isBigger(Annotation a, Annotation b){ >>>> if(isNull(a,b)){ >>>> return false; >>>> } >>>> if(a.getBegin() == b.getBegin() && a.getEnd() < b.getEnd()){ >>>> return true; >>>> } >>>> if(b.getBegin() < a.getBegin() && a.getEnd() == b.getEnd()){ >>>> return true; >>>> } >>>> if(b.getBegin() < a.getBegin() && a.getEnd() < b.getEnd()){ >>>> return true; >>>> } >>>> >>>> return false; >>>> } >>>> ================================================================== >>>> public static boolean isBetween(Annotation a, Annotation b, Annotation >>>> c){ >>>> if(isNull(a,b,c)){ >>>> return false; >>>> } >>>> Annotation min = getMin(a,b); >>>> Annotation max = getMax(a,b); >>>> >>>> if(isOverlapping(a,c) || isOverlapping(b,c)){ >>>> return true; >>>> } >>>> >>>> if(c.getBegin() > min.getEnd() && c.getEnd() < max.getBegin()){ >>>> return true; >>>> } >>>> >>>> return false; >>>> } >>>> ================================================================== >>>> public static Annotation getMax(Annotation a, Annotation b){ >>>> isNull(a,b); >>>> if(a.getBegin() >= b.getBegin()){ >>>> return a; >>>> } >>>> >>>> return b; >>>> } >>>> ================================================================== >>>> public static Annotation getMin(Annotation a, Annotation b){ >>>> isNull(a,b); >>>> if(a.getEnd() <= b.getEnd()){ >>>> return a; >>>> } >>>> >>>> return b; >>>> } >>>> ================================================================== >>>> >>>> I've posted all functions that are used by the rule. Actually it crushes >>>> if I use more than 2 statements in the isEqual() call in $a5. >>>> It works with !isEqual($a3,$a4) && !isEqual($a3,$a5) && >>>> !isEqual($a4,$a5) >>>> but not with !isEqual($a3,$a4,$a5). >>>> >>>> So do you got an idea where the problem comes from? >>>> >>>> JB >>>> >>>> >>>> ----- Ursprüngliche Mail ----- >>>> Von: "Wolfgang Laun" <[email protected]> >>>> An: "Rules Users List" <[email protected]> >>>> Gesendet: Mittwoch, 6. März 2013 15:09:47 >>>> Betreff: Re: [rules-users] Cannot invoke method because >>>> of ArrayIndexOutOfBoundsException >>>> >>>> Nice try - but, please, don't. Kindly post the code that actually >>>> causes your problem. >>>> >>>> -W >>>> >>>> >>>> On 06/03/2013, Bojan Janisch <[email protected]> wrote: >>>>> Hello Guys, >>>>> >>>>> sorry to bother you with this problem, but I'm out of ideas. >>>>> I'm using Drools in textmining-context and in basic I have >>>>> a function that checks 2 named entites for equality to >>>>> ensure that the entities are all different and that the rules >>>>> do work only on different named entity objects: >>>>> >>>>> public static boolean isEqual(Annotation a, Annotation b){ >>>>> if(a.equals(b)){ >>>>> return true; >>>>> } >>>>> >>>>> return false; >>>>> } >>>>> >>>>> Sometimes there are conditions that need tests of more than >>>>> 2 named entites. For this I've written a super method that >>>>> calls the isEqual method in a loop: >>>>> >>>>> public static boolean isEqual(Annotation... a){ >>>>> ArrayList<Annotation> outLoop = new >>>>> ArrayList<Annotation>(Arrays.asList(a)); >>>>> ArrayList<Annotation> inLoop = new >>>>> ArrayList<Annotation>(Arrays.asList(a)); >>>>> >>>>> for (Annotation anno1 : outLoop) { >>>>> inLoop.remove(anno1); >>>>> for (Annotation anno2 : inLoop) { >>>>> if(isEqual(anno1,anno2)){ >>>>> return true; >>>>> } >>>>> } >>>>> } >>>>> >>>>> return false; >>>>> } >>>>> >>>>> >>>>> My rules could (theoretically) now call the function >>>>> eval(isEqual($ne1,$ne2)) or >>>>> eval(isEqual($ne1,$ne2,$ne3) or even >>>>> eval(isEqual($ne1,$ne2,$ne3,$ne4,$ne5)) and so on. >>>>> >>>>> So there starts my problem: >>>>> >>>>> Each time I'm getting an ArrayIndexOutOfBounds Exception from the >>>>> second >>>>> method that looks like this: >>>>> >>>>> java.lang.RuntimeException: cannot invoke method: isEqual >>>>> ... >>>>> at java.lang.Thread.dispatchUncaughtException(Thread.java:1888) >>>>> Caused by: java.lang.ArrayIndexOutOfBoundsException: 3 >>>>> at >>>>> org.mvel2.optimizers.impl.refl.nodes.MethodAccessor.executeAll(MethodAccessor.java:149) >>>>> at >>>>> org.mvel2.optimizers.impl.refl.nodes.MethodAccessor.getValue(MethodAccessor.java:48) >>>>> at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:108) >>>>> at >>>>> org.mvel2.compiler.ExecutableAccessor.getValue(ExecutableAccessor.java:38) >>>>> ... >>>>> >>>>> Could someone explain me what's wrong with my code? Thanks for any >>>>> help. >>>>> >>>>> Greetings >>>>> JB >>>>> _______________________________________________ >>>>> rules-users mailing list >>>>> [email protected] >>>>> https://lists.jboss.org/mailman/listinfo/rules-users >>>>> >>>> _______________________________________________ >>>> rules-users mailing list >>>> [email protected] >>>> https://lists.jboss.org/mailman/listinfo/rules-users >>>> >>>> _______________________________________________ >>>> rules-users mailing list >>>> [email protected] >>>> https://lists.jboss.org/mailman/listinfo/rules-users >>> >>> _______________________________________________ >>> rules-users mailing list >>> [email protected] >>> https://lists.jboss.org/mailman/listinfo/rules-users >>> >>> _______________________________________________ >>> rules-users mailing list >>> [email protected] >>> https://lists.jboss.org/mailman/listinfo/rules-users >> >> _______________________________________________ >> rules-users mailing list >> [email protected] >> https://lists.jboss.org/mailman/listinfo/rules-users >> >> _______________________________________________ >> rules-users mailing list >> [email protected] >> https://lists.jboss.org/mailman/listinfo/rules-users > > _______________________________________________ > rules-users mailing list > [email protected] > https://lists.jboss.org/mailman/listinfo/rules-users > > _______________________________________________ > rules-users mailing list > [email protected] > https://lists.jboss.org/mailman/listinfo/rules-users _______________________________________________ rules-users mailing list [email protected] https://lists.jboss.org/mailman/listinfo/rules-users
