Friday, April 25, 2008

External function calls

The latest release of the Rule Manager allows to import external functions into the business vocabulary. As a little exercise I tried to get the current weather condition for a zipcode (maybe I can write some rules if I should bring my umbrella while I leave my house in L.A.)

Initially I intended to call a webservice, but it seems that all free weather webservice calls is something from the past. Yahoo offers weather information as an RSS feed. So a simple XPath query can select the information that I'm interested in:

Here is the code (note the FunctionAttribute decoration on the method)


1 using System.IO;

2 using System.Net;

3 using System.Xml;

4 using AcumenBusiness.IModel;

5 using Type=AcumenBusiness.IModel.Type;

6

7 namespace TestCallWebService

8 {

9 [Concept("Weather info", "Try to get weather forecast from different services")]

10 public class WeatherInfoProvider

11 {

12 private static readonly string YahooWeatherURLFormat = "http://weather.yahooapis.com/forecastrss?p={0}";

13

14 [Term("workaround", "import function requires one field. (bug)")]

15 private string dummyField;

16 public string DummyField

17 {

18 get { return dummyField; }

19 set { dummyField = value; }

20 }

21

22 [Function("Get temperature", "Get the weather info from Yahoo",

23 ReturnType = Type.text,

24 ArgumentTypes = new Type[] { Type.integer })]

25 public static string GetWeatherInfoAsFeed(int zipCode)

26 {

27 HttpWebRequest request = (HttpWebRequest) WebRequest.Create(string.Format(YahooWeatherURLFormat, zipCode));

28 // execute the request

29 HttpWebResponse response = (HttpWebResponse) request.GetResponse();

30

31 // we will read data via the response stream

32 Stream resStream = response.GetResponseStream();

33 XmlDocument rssFeed = new XmlDocument();

34 rssFeed.Load(resStream);

35

36 //set an XmlNamespaceManager since we have to make explicit namespace searches

37 XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(rssFeed.NameTable);

38 //Add the namespaces used in the xml doc to the XmlNamespaceManager.

39 xmlnsManager.AddNamespace("yweather", "http://xml.weather.yahoo.com/ns/rss/1.0");

40

41 XmlNode weatherCondition = rssFeed.SelectSingleNode("/rss/channel/item/yweather:condition/@temp", xmlnsManager);

42 if (weatherCondition != null) {

43 return weatherCondition.Value;

44 }

45 return null;

46 }

47 }

48 }



With the Import Schema adapter I can import this function and call it from my business rules. The coolest part is that you can invoke this from the Interactive Rule Map. So you can see how your rules are executing with this external data. It seems to be 76 fahrenheid in L.A.
Nice weather to jump on the bike and cycle to work...