/Documentation/Examples

wc Example

This example is a sort of "Hello, World!" with MetaRBE. Demonstrates how to parse a text file and recognize patterns like digits, words, lines. In the end it shows statistics for counted words, digits and lines of text.

Sources:

Main.java

Main.java is major part of this example. It illustrates how to use MetaRBE API. We create a session, describe events, rules and actions.

			package net.sf.metarbe.example.wc;

		import net.sf.metarbe.ActionEvent;
		import net.sf.metarbe.DuplicateNameException;
		import net.sf.metarbe.EventGenerator;
		import net.sf.metarbe.RuleAction;
		import net.sf.metarbe.RuleContext;
		import net.sf.metarbe.RuleSemanticModel;
		import net.sf.metarbe.RuleRuntime;
		import net.sf.metarbe.RuleServiceProvider;
		import net.sf.metarbe.RuleSession;
		import net.sf.metarbe.RuleSessionEvent;
		import net.sf.metarbe.RuleSessionType;
		import net.sf.metarbe.SessionFactoryIsNotSetException;
		import net.sf.metarbe.impl.RuleSetManagerImpl;
		import net.sf.metarbe.impl.RuleServiceProviderImpl;
		
		public class Main {
			public static int digits = 0; 
			public static int words = 0;
			public static int lines = 0;
		
			/**
			 * @param args
			 */
			public static void main(String[] args) {
				
				if(args.length==0){
					System.out.println("USAGE: java -cp metarbe.jar net.sf.metarbe.example.wc.Main <filename>");
					System.exit(0);
				}
				
				RuleServiceProvider rsp = RuleServiceProviderImpl.getRuleServiceProvider();
				
				// Create runtime instance
				RuleRuntime rr = rsp.getRuleRuntime();
				// Our session is not aimed to keep state of process in between invocations
				rr.registerRuleSessionFactory(new WcSessionFactory(), RuleSessionType.STATELESS_SESSION);
				
				// Create a dictionary to denote certain states in processing
				final RuleSemanticModel ruleLayout = new RuleSemanticModel();
				try {
					// textparser is main actor here, so introduce it
					ruleLayout.addContext("textparser");
					
					// context of text parser can allow the following states   
					ruleLayout.addState("failed"); // text parser failed to recognize a token or system error occured
					ruleLayout.addState("word-ahead"); // text parser went word ahead
					ruleLayout.addState("line-ahead"); // text parser wen line of text ahead
				} catch (DuplicateNameException e) {
					e.printStackTrace();
				}
				
				// EventGenerator allows customize emitting event
				EventGenerator eg = new EventGenerator(){
					public RuleSessionEvent createEventInContext(RuleContext aRuleContext, RuleSession aSession) {
						return new WcEvent(
								aRuleContext, 
								aSession.getValue("source"), 
								aSession.getValue("textData").toString());
					}
				};
				
				try {
					// Create a session object
					RuleSession ruleSession = rr.createRuleSession (ruleLayout, RuleSessionType.STATELESS_SESSION);
					
					// Register EventGenerator instance per context state
					ruleSession.addEventGenerator ( ruleLayout.getRuleContext("textparser:failed"), eg );
					ruleSession.addEventGenerator ( ruleLayout.getRuleContext("textparser:word-ahead"), eg );
					ruleSession.addEventGenerator ( ruleLayout.getRuleContext("textparser:line-ahead"), eg );
					
					// Create an instance of RuleSetmanager that dispatches events to rules
					RuleSetManagerImpl ad = new RuleSetManagerImpl("Text Recognition Dispatcher", ruleSession );
					
					// Add a rule to count recognized in text digits
					ad.createRule("count for digits", 
						ruleLayout.getRuleContext("textparser:word-ahead"), 
						new NumberMatch ( ), 
						new RuleAction ( ) {
							public void onActionEvent(ActionEvent evt) {
								digits++;
							}
						}
					);
					
					// Add a rule to count recognized in text words
					ad.createRule("count for words", 
						ruleLayout.getRuleContext ("textparser:word-ahead"), 
						new WordMatch(), 
						new RuleAction(){
							public void onActionEvent(ActionEvent evt) {
								words++;
							}
						}
					);
					
					// Add a rule to count recognized in text lines
					ad.createRule("count for lines", 
						ruleLayout.getRuleContext ("textparser:line-ahead"), 
						new RuleAction(){
							public void onActionEvent (ActionEvent evt) {
								lines++;
							}
						}
					);
					
					// Error handler is also can be a rule
					ad.createRule("recognition has failed", 
						ruleLayout.getRuleContext ("textparser:failed"), 
						new RuleAction(){
							public void onActionEvent(ActionEvent evt) {
								System.err.println("Text recognition has failed due to: "+((WcEvent)evt.getRuleSessionEvent()).getTextData());
							}
						}
					);
					
					// Run processing with a filename given as cmdline argument
					ad.executeRules (args[0]);
					System.out.println("File "+args[0]+": lines="+lines+" words="+words+" numbers="+digits);
					
					
				} catch (SessionFactoryIsNotSetException e) {
					e.printStackTrace();
				}
			}
		}

		

WcSession.java

This class designed to parse text file and discover elements such as words and lines. It also signals a failure if given file is not readable. In this example session implements StatelessSession interface and it is most low-level implementation. There are implementations for session to get rid of overloading overhead.

			package net.sf.metarbe.example.wc;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.metarbe.EventGenerator;
import net.sf.metarbe.RuleActivator;
import net.sf.metarbe.RuleContext;
import net.sf.metarbe.RuleSemanticModel;
import net.sf.metarbe.RuleContextValidation;
import net.sf.metarbe.RuleSessionSupport;
import net.sf.metarbe.RuleSessionType;
import net.sf.metarbe.StatelessRuleSession;

public class WcSession implements StatelessRuleSession {
	private RuleSessionSupport sessionSupport = new RuleSessionSupport();
	protected String filename;
	
	public WcSession ( ) {
		
	}
	
	public void addEventGenerator(RuleContext aRuleContext,EventGenerator anEventGenerator) {
		sessionSupport.addEventGenerator(aRuleContext, anEventGenerator);
	}

	public void addEventGenerator(RuleContext aRuleContext, EventGenerator anEventGenerator, int idx) {
		sessionSupport.addEventGenerator(aRuleContext, anEventGenerator, idx);
	}
	
	public void bindParameter(String aParamName, Object aValue) {
		sessionSupport.bindParameter(aParamName, aValue);
	}

	public void executeRules(Object data) {
		filename = (String)data;
		bindParameter("source", data);
		try {
			BufferedReader reader = new BufferedReader(new FileReader(filename));
			String line = null;
			while((line = reader.readLine ( ))!=null){
				if(line.length()==0){
					sessionSupport.bindParameter("textData", "");
					sessionSupport.fireEventInContext(getRuleSemanticModel().getRuleContext("textparser:line-ahead"), this);
					continue;
				}
				
				String[] words = line.split(" ");
				for (String word : words) {
					sessionSupport.bindParameter("textData", word);
					sessionSupport.fireEventInContext(getRuleSemanticModel().getRuleContext("textparser:word-ahead"), this);
				}
				sessionSupport.bindParameter("textData", "");
				sessionSupport.fireEventInContext(getRuleSemanticModel().getRuleContext("textparser:line-ahead"), this);
			}
			
		} catch (FileNotFoundException e) {
			sessionSupport.bindParameter("textData", e.getMessage());
			sessionSupport.fireEventInContext(getRuleSemanticModel().getRuleContext("textparser:failed"), this);
		} catch (IOException e) {
			sessionSupport.bindParameter("textData", e.getMessage());
			sessionSupport.fireEventInContext(getRuleSemanticModel().getRuleContext("textparser:failed"), this);
		}
	}

	public Iterator getParameters() {
		return sessionSupport.getParameters();
	}

	public RuleActivator getRuleActivator() {
		return sessionSupport.getRuleActivator();
	}

	public RuleSemanticModel getRuleSemanticModel() {
		return sessionSupport.getRuleSemanticModel();
	}

	public RuleSessionType getSessionType() {
		return RuleSessionType.STATELESS_SESSION;
	}

	public Object getValue(String aParamName) {
		return sessionSupport.getValue(aParamName);
	}

	public void setRuleActivator(RuleActivator aRuleActivator) {
		sessionSupport.setRuleActivator(aRuleActivator);
	}

	public void setRuleSemanticModel(RuleSemanticModel aRuleModel) {
		sessionSupport.setRuleSemanticModel(aRuleModel);
	}

	public Map<RuleContext, RuleContextValidation> getContextValidations() {
		return sessionSupport.getContextValidations();
	}
	
	public Map<RuleContext, List<EventGenerator>> getEventGenerators() {
		return getEventGenerators();
	}
	
	public void unbindParameter(String aParamName) {
		sessionSupport.unbindParameter(aParamName);
	}
	
	public void release() { }
	
	public void removeEventGenerator(RuleContext aRuleContext, EventGenerator anEventGenerator) {
		sessionSupport.removeEventGenerator(aRuleContext, anEventGenerator);
	}
}

		

WcSessionFactory.java

This factory used to create a session object. For more complex cases it can be useful in that sense that use might want to differentiate session objects depending ongiven parameter (FactoryMethod pattern)

			package net.sf.metarbe.example.wc;

import net.sf.metarbe.RuleSession;
import net.sf.metarbe.RuleSessionFactory;

public class WcSessionFactory implements RuleSessionFactory {
	public RuleSession createRuleSession() {
		return new WcSession();
	}

}

		

WcEvent.java

This event object is a contract between rules and session. In general is ValueObject pattern.

			package net.sf.metarbe.example.wc;

import net.sf.metarbe.RuleContext;
import net.sf.metarbe.RuleSessionEvent;

public class WcEvent extends RuleSessionEvent {
	private String textData; 
	public WcEvent(RuleContext aRuleContext, Object source, String textData) {
		super(aRuleContext, source);
		this.textData = textData;
	}

	@Override
	public Object getMatchedValue() {
		return getTextData();
	}
	
	public String getTextData() {
		return textData;
	}

}

		

WordMatch.java

Determines if given data is a word and not number.

			package net.sf.metarbe.example.wc;

import net.sf.metarbe.RuleConstraint;

public class WordMatch implements RuleConstraint {
	public boolean match(Object aValue) {
		try {
			Double.parseDouble(String.valueOf(aValue));
		} catch (NumberFormatException e) {
			return true;
		}
		return false;
	}

}

		

NumberMatch.java

Determines if given data is number and not a word

			package net.sf.metarbe.example.wc;

import net.sf.metarbe.RuleConstraint;

public class NumberMatch implements RuleConstraint {
	public boolean match(Object aValue) {
		try {
			Double.parseDouble ( String.valueOf(aValue) );
		} catch (NumberFormatException e) {
			return false;
		}
		return true;
	}

}