Subsections
Getting started with a simple exampleAt this point your JBuilder environment is set up and ready to go. All you need now is a test project. So, the next thing we'll do is create a really simple example to get you started.
Our simple exampleFor the purposes of this article I'm going to create a really simple anti-spam filter. At this point I'm going to make several simplifying assumptions so we can focus on how to use ABLE, instead of all the complexities of spam filtering. To this end I'm going to assume that an email message consists of a Sender, Recipient, Subject, and a Message. I'm also going to ignore attachments for now. Don't worry though, because over time I'll add more complexity to the rules.
Filtering rulesWhen you start thinking about ways of determining whether or not an email message is spam, you'll soon realize that there are many rules that you can come up with. Having worked with this for a while, I can say that these are some of the most obvious rules:
Of course there are many, many more ways to determine whether a message is spam or not, but these are a few simple rules we can explore within the context of this article.
One simple ruleTo get started with the ABLE syntax I'm going to start with a much simpler rule: If the ``from'' field is equal to the string ``spammer'' then I'm going to call the email a spam message. Given this one simple rule, let's implement it using ABLE. This will help us get started with ABLE's Ruleset grammar. Fortunately it's pretty simple, so let's just dive right in with our example.
RuleSet for the ``simple example''Here is the ruleset for the simple example:
ruleset Email
{
// define the variables we'll be using
variables
{
String result;
String to;
String subject;
String content;
String from;
}
// inputs we get from the calling program
inputs{from,to,subject,content};
// outputs we return to the calling program
outputs{result};
// main processing logic goes here
void process() using Script
{
: If (from == "spammer")
result = "SPAM";
}
// anything we want to do after the main processing
void postProcess()
{
: println("Ruleset concludes the email is a " + result + " email.");
}
}
In this example I'm trying to keep the ruleset as simple as possible. Everything you see in this example, other than the comments and the postProcess method, is required. The example begins by declaring that we have a Ruleset named Email. That is followed by a variables section. Here we declare the local variables we're going to use in our ruleset. For our purposes this includes variables that we need to examine an email message, including fields named result, to, subject, content, from. This section is followed by an inputs method. This is a special method in ABLE, and it's used to receive data from a calling program. Here I'm expecting the calling program to pass four fields of information, corresponding to the from, to, subject, and content fields. The next method is named outputs. This is also a special method in an ABLE ruleset, and it's used to pass information back to the calling program. In my example I'm just passing back a String variable named result. The result variable is set in the next method, process(). The process method is where the main processing of the Ruleset begins. This is where you will put the rules for your application. Of course in this example we have one very simple rule: If the from field is equal to the String ``spammer``, then we're going to set result equal to the String ``SPAM``. (Of course this isn't very complicated or ``real world'' yet, but I'll start adding some more rules shortly.) The last portion of the ruleset is the postProcess() method. This method is used for any work you want to do after that main processing of the process method is complete. Here I'm just using the postProcess method to print a String out after the main processing has concluded. As mentioned earlier, this method is not required by ABLE, but it is helpful during testing. The next thing we need is the Java source code to drive our example ruleset. We've seen the inputs that are expected from the Java program, and the outputs that are being sent back to it, so let's see how that program is constructed.
Source code for the ``simple example''In the sample code below I'm trying to create the most simple Java program I can to demonstrate how to connect to an ABLE Ruleset. I'll discuss the code after the listing.
package email;
import java.util.Iterator;
import com.ibm.able.Able;
import com.ibm.able.AbleException;
import com.ibm.able.rules.AbleRuleSet;
public class EmailRuleSetApp
{
public static void main(String[] args)
{
try
{
// retrieve the rule set
String rules = "C:/Projects/BorlandConference2004/AI/ABLE/JB_ABLE_Test/src/email/email.arl";
AbleRuleSet ruleSet = new AbleRuleSet();
ruleSet.parseFromARL(rules);
ruleSet.init();
// create our (fake) data
String[][] data = new String[][]{
{"spammer", "to", "subject", "contents"},
};
String[] input = null;
Object[] output = null;
Able.startTraceLogging(Able.TRC_LOW, Able.MSG_NONE, null);
Able.TraceLog.text(Able.TRC_LOW, "Input current: " + displayBuffer((Object[]) ruleSet.getInputBuffer()));
Able.TraceLog.text(Able.TRC_LOW, "Output current: " + displayBuffer((Object[]) ruleSet.getOutputBuffer()));
for (int i=0; i<data.length; i++)
{
Able.TraceLog.text(Able.TRC_LOW, "Starting Run " + i + " ----------");
// pass data to the agent and get the result
output = (Object[]) ruleSet.process(input = data[i]);
// show the input that was passed and the result obtained
Able.TraceLog.text(Able.TRC_LOW, "Input result: " + displayBuffer(input));
Able.TraceLog.text(Able.TRC_LOW, "Output result: " + displayBuffer(output));
}
}
catch (AbleException ae)
{
if (ae.getExceptions() == null)
{
System.out.println(ae.getLocalizedMessage());
} else
{
Iterator it = ae.getExceptions().iterator();
while (it.hasNext())
{
Exception e = (Exception) it.next();
System.out.println(e.getLocalizedMessage());
}
}
} catch (Exception exp)
{
System.out.println(exp.getLocalizedMessage());
exp.printStackTrace();
}
System.exit(0);
}
// method directly from the ibm "animal" example
private static String displayBuffer(Object[] buf)
{
StringBuffer buffer = new StringBuffer("");
if (buf == null)
{
buffer.append(buf);
} else
{
for (int i = 0; i < buf.length; i++) buffer.append(buf[i] + " ");
}
return buffer.toString();
}
// method directly from the ibm "animal" example
private static String displayBuffer(double[] buf)
{
StringBuffer buffer = new StringBuffer("");
if (buf == null)
{
buffer.append(buf);
} else
{
for (int i = 0; i < buf.length; i++) buffer.append(buf[i] + " ");
}
return buffer.toString();
}
}
Discussion of the ``simple example'' source code The beginning of the program is straightforward. I'm creating a class named EmailRuleSetApp in a package named email. I start by importing several classes that I'll need later in the program. In the main method I read in my ruleset with the following code:
// retrieve the rule set String rules = "C:/Projects/BorlandConference2004/AI/ABLE/JB_ABLE_Test/src/email/email.arl"; AbleRuleSet ruleSet = new AbleRuleSet(); ruleSet.parseFromARL(rules); ruleSet.init(); As you can see this is a straightforward process of defining the location of my ruleset, and then reading its contents into an AbleRuleSet object. The next thing I do is to create a little bit of sample data to test the ruleset. In the code below I create a two-dimensional String array of content that I'm going to pass into the ruleset for processing.
// create our (fake) data
String[][] data = new String[][]{
{"spammer", "to", "subject", "contents"},
};
Next, I create String arrays for the input-to and output-from the ruleset. I then turn on a little bit of logging so I can print some output. Next is the for loop, where I start processing through my simulated set of data. For each row of Strings in my data array, I call the process method of the ruleSet object to determine whether or not this set of data represents a spam message. Note that I'm passing in the data array as input, and I'm also receiving output from the process method. For each run through the for loop I'm then printing the result that is received from process method.
String[] input = null;
Object[] output = null;
Able.startTraceLogging(Able.TRC_LOW, Able.MSG_NONE, null);
for (int i=0; i<data.length; i++)
{
Able.TraceLog.text(Able.TRC_LOW, "Starting Run " + i + " ----------");
// pass data to the agent and get the result
output = (Object[]) ruleSet.process(input = data[i]);
Able.TraceLog.text(Able.TRC_LOW, "Output result: " + displayBuffer(output));
}
At this point I'm going to skip any discussion of the exceptions that can be thrown by the AbleRuleSet because, other than knowing that exceptions can be thrown, they are not important to this introduction. I'm also going to skip any discussion of the displayBuffer method, because it is simply a convenience method I found in the ABLE examples to let me print my buffers.
Output from the ``simple example''Running this program yields the following output:
Starting Run 0 ---------- Ruleset concludes the email is a SPAM email. 2004.07.16 14:21:18.279 Output result: SPAM As you can see, the result of this run is that the rules engine interprets the information given as being a spam message. Simple, right? (It's sad, but you wouldn't believe how long it took me to get to that point.) Now that we've made it through this first hurdle, let's see what we can do to make this a little more complicated.
Next: A more complicated example Up: AI Previous: Configuring JBuilder to work |