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 <bojan.janisch(a)scai.fraunhofer.de> 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" <wolfgang.laun(a)gmail.com>
An: "Rules Users List" <rules-users(a)lists.jboss.org>
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 <bojan.janisch(a)scai.fraunhofer.de> 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" <wolfgang.laun(a)gmail.com>
> An: "Rules Users List" <rules-users(a)lists.jboss.org>
> 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 <bojan.janisch(a)scai.fraunhofer.de> 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" <wolfgang.laun(a)gmail.com>
>> An: "Rules Users List" <rules-users(a)lists.jboss.org>
>> 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 <bojan.janisch(a)scai.fraunhofer.de> 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" <wolfgang.laun(a)gmail.com>
>>> An: "Rules Users List" <rules-users(a)lists.jboss.org>
>>> 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 <bojan.janisch(a)scai.fraunhofer.de> 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
>>>> rules-users(a)lists.jboss.org
>>>>
https://lists.jboss.org/mailman/listinfo/rules-users
>>>>
>>> _______________________________________________
>>> rules-users mailing list
>>> rules-users(a)lists.jboss.org
>>>
https://lists.jboss.org/mailman/listinfo/rules-users
>>>
>>> _______________________________________________
>>> rules-users mailing list
>>> rules-users(a)lists.jboss.org
>>>
https://lists.jboss.org/mailman/listinfo/rules-users
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users(a)lists.jboss.org
>>
https://lists.jboss.org/mailman/listinfo/rules-users
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users(a)lists.jboss.org
>>
https://lists.jboss.org/mailman/listinfo/rules-users
>
> _______________________________________________
> rules-users mailing list
> rules-users(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/rules-users
>
> _______________________________________________
> rules-users mailing list
> rules-users(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/rules-users
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users