Object Models for an Example Help Desk

public static class Problem { Note: Drools has problems dealing with Java 5 enums as match types so I use static integers here. In general, using enums is much better. final public static int NONE = 0; appliance types: final public static int REFRIGERATOR = 101; final public static int MICROWAVE = 102; final public static int TV = 103; final public static int DVD = 104; environmentalData possible values: final public static int CIRCUIT_BREAKER_OFF = 1002; final public static int LIGHTS_OFF_IN_ROOM = 1003; problemType possible values: final public static int NOT_RUNNING = 2001; final public static int SMOKING = 2002; final public static int ON_FIRE = 2003; final public static int MAKES_NOISE = 2004; long serviceId = 0; unique ID for all problems dealing with customer problem int applianceType = NONE; int problemType = NONE; int environmentalData = NONE; public Problemlong serviceId, int type { this.serviceId = serviceId; this.applianceType = type; } public String toString { return [Problem: + enumNames.getapplianceType + problem type: + enumNames.getproblemType + environmental data: + enumNames.getenvironmentalData + ]; } public long getServiceId { return serviceId; } public int getEnvironmentalData { return environmentalData; } public int getProblemType { return problemType; } static MapInteger, String enumNames = 92 new HashMapInteger, String; static { enumNames.put0, NONE; enumNames.put1002, CIRCUIT_BREAKER_OFF; enumNames.put1003, LIGHTS_OFF_IN_ROOM; enumNames.put2001, NOT_RUNNING; enumNames.put2002, SMOKING; enumNames.put2003, ON_FIRE; enumNames.put2004, MAKES_NOISE; enumNames.put101, REFRIGERATOR; enumNames.put102, MICROWAVE; enumNames.put103, TV; enumNames.put104, DVD; } } It is unfortunate that the current version of Drools does not work well with Java 5 enums – the P roblem class would have been about half as many lines of code no need to map integers to meaningful descriptions for toString and the example would also be more type safe. I used constant values like REFRIGERATOR and RUNNING to represent pos- sible values for the member class attributes like applianceT ype, problemT ype, and environmentalData. There is obviously a tight binding from the Java POJO classes like P roblem to the rules that use these classes to represent objects in work- ing memory. We will see a few example help desk rules in the next section.

5.5.2 Drools Rules for an Example Help Desk

This demo help desk system is not interactive. The Java code in the next section loads the rule set that we are about to develop and then programmatically adds test facts into working memory that simulate two help desk customer service issues. This is an important example since you will likely want to add data directly from Java code into Drools working memory. There are several rules defined in the example file HelpDesk.drl and we will look at a few of them here. These rules are intended to be a pedantic example of both how to match attributes in Java POJO classes and to show a few more techniques for writing Drools rules. I used to use the Lisp based OPS5 to develop expert systems and I find the combina- tion of Java and Drools is certainly “less agile” to use. I found myself writing a rule, then editing the POJO class Problem to add constants for things that I wanted to use in the rule. With more experience, this less than interactive process might become 93 more comfortable for me. As in the blocks world example, we want to place the rules file in the same package as the Java code using the rules file and import any POJO classes that we will use in working memory: package com.markwatson.examples.drool import com.markwatson.examples.drool. DroolsHelpDesk.Problem; The first rule sets a higher than default rule salience so it will fire before any rules with the default rule salience a value of zero. This rule has a feature that we have not seen before: I have no matching expressions in the “when” clause. All Java Problem instances will match the left-hand side of this rule. rule Print all problems salience 100 when p : Problem then System.out.printlnFrom rule ’Print all problems’: + p; end The following rule matches an instance of the class P roblem in working memory that has a value of “Problem.CIRCUIT BREAKER OFF” for the vakue of attribute environmentalData. This constant has the integer value of 1002 but is is obvi- ously more clear to use meaningful constant names: rule Reset circuit breaker when p1 : ProblemenvironmentalData == Problem.CIRCUIT_BREAKER_OFF then System.out.printlnReset circuit breaker: + p1; end The last rule could perhaps be improved by having it only fire if any appliance was not currently running; we make this check in the next rule. Notice that in the next rule we are matching different attributes problemT ype and environmentalData and it does not matter if these attributes match in a single working memory element or two different working memory elements: 94