cluis92
cluis92

Reputation: 932

How to loop through a list to check if an item is a memberOf another list

I want to check if any item from a list of diagnosis codes exists in another list.

I am new to Drools and I'm still trying to decide on the best approach as the current one isn't working (the output says null when it should be returning 'true').

Java POJO

public class EligibilityDomainObject {
    
    private List<String> listOfString;  
    public List<String> getListOfString() {  
         return listOfString;  
    }  
    public void setListOfString(List<String> listOfString) {  
         this.listOfString = listOfString;  
    }  
    public void addString(String value) {  
         if (listOfString == null) {  
              listOfString = new ArrayList<String>();  
         }  
         listOfString.add(value);  
    }  
    private Boolean isComplexPhysicalHealth;
    public Boolean getIsComplexPhysicalHealth() {
        return this.isComplexPhysicalHealth;
    }

    public void setIsComplexPhysicalHealth(Boolean isComplexPhysicalHealth) {
        this.isComplexPhysicalHealth = isComplexPhysicalHealth;
    }

Drools

rule "Problems related to social environment"
    when
        $eligibilityDomainObject:EligibilityDomainObject($listOfString : listOfString,
            $listOfString memberOf "F77 EOO F99" )
    then
        $eligibilityDomainObject.setIsComplexPhysicalHealth(true);
end

Main

    public static void main(String[] args) {
        SpringApplication.run(RulesEngineApplication.class, args);
        

        try {
            KieServices kieServices = KieServices.Factory.get();
            KieContainer kContainer = kieServices.getKieClasspathContainer();

            KieSession kSession = kContainer.newKieSession("ksession-rules");
            
            EligibilityDomainObject eligibilityDomainObject = new EligibilityDomainObject(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);

            eligibilityDomainObject.addString("F77");
            eligibilityDomainObject.addString("F99");
            System.out.println("List of diagnosis codes: "+ eligibilityDomainObject.getListOfString().toString());
            kSession.insert(eligibilityDomainObject);
            kSession.fireAllRules();
            System.out.println("complex phys health flag: "+ eligibilityDomainObject.getIsComplexPhysicalHealth());
            
            kSession.dispose(); 
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

output

List of diagnosis codes: [Z590, E0800]

complex phys health flag: null

expected output

List of diagnosis codes: [Z590, E0800]

complex phys health flag: true

Upvotes: 1

Views: 264

Answers (2)

Mykhaylo Adamovych
Mykhaylo Adamovych

Reputation: 20966

Your rule will misbehave against 'F', 'F7', 'F9'...

Consider few other approaches:

rule "Problems related to social environment"
    when
        $eligibilityDomainObject:EligibilityDomainObject($listOfString : listOfString)
            value: String(value in ("F77", "EOO", "F99") ) from $listOfString
    then
        $eligibilityDomainObject.setIsComplexPhysicalHealth(true);
end

According to documentation, one need to

Avoid using the from element when you can insert all facts into the working memory of the Drools engine or use nested object references in your constraint expressions."

Following will cause the rule to be triggered only once per EligibilityDomainObject, not per each matching value:

import static org.apache.commons.collections4.CollectionUtils.containsAny;

rule "Problems related to social environment"
    when
        $eligibilityDomainObject:EligibilityDomainObject(containsAny(listOfString, "F77", "EOO", "F99"))
    then
        $eligibilityDomainObject.setIsComplexPhysicalHealth(true);
end

gather matching values in one go

import static org.apache.commons.collections4.CollectionUtils.intersection;
import static com.google.common.collect.Sets.newHashSet;

rule "Problems related to social environment"
    when
        $eligibilityDomainObject:EligibilityDomainObject(
            $values : intersection(listOfString, newHashSet("F77", "EOO", "F99")), 
            !$values.isEmpty())
    then
        $eligibilityDomainObject.setIsComplexPhysicalHealth(true);
        System.out.println($values);
end

Upvotes: 1

cluis92
cluis92

Reputation: 932

I was able to solve it using the 'from' keyword

rule "Problems related to social environment"
    when
        $eligibilityDomainObject:EligibilityDomainObject($listOfString : listOfString)
            value: String(value memberOf "F77 EOO F99" ) from $listOfString
    then
        $eligibilityDomainObject.setIsComplexPhysicalHealth(true);
end

Upvotes: 1

Related Questions