package com.ibm.able.examples.rules;

//====================================================================
//
// Licensed Materials - Property of IBM
//
// "Restricted Materials of IBM"
//
// Product: com.ibm.able.examples.ableagent
//
// (C) Copyright IBM Corp. 2000 All Rights Reserved.
//
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with
// IBM Corp.
//
//
//                             DISCLAIMER
//                             ----------
//
// This material contains programming source code for your consideration.
// These examples have not been thoroughly tested under all conditions.
// IBM, therefore, cannot guarantee or imply reliability, serviceability,
// performance or function of these programs.  All programs contained
// herein are provided to you "AS IS".  THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
// DISCLAIMED.
//
//====================================================================

//====================================================================
// Imports
//====================================================================
import java.util.Hashtable;
import java.util.Vector;

import com.ibm.able.AbleException;
import com.ibm.able.data.AbleData;
import com.ibm.able.data.AbleDoubleLiteral;
import com.ibm.able.data.AbleExpression;
import com.ibm.able.data.AbleRd;
import com.ibm.able.data.AbleVariable;
import com.ibm.able.rules.AbleAssertionClause;
import com.ibm.able.rules.AbleAssertionRule;
import com.ibm.able.rules.AbleRule;
import com.ibm.able.rules.AbleRuleBlock;
import com.ibm.able.rules.AbleRuleSet;

/**
 * Construct a ruleset using the APIs.
 *
 * The basic steps are: 
 * <ol>
 *   <li>create instance of AbleRuleSetBean
 *    <li>set name 
 *    <li>set comment (optional) 
 *    <li>declare any imports 
 *    <li>declare any libraries 
 *    <li>declare any predicates 
 *    
 *    <li>declare any global variables 
 * 
 *    <li>declare any functions 
 * 
 *    <li>set the input vars (if any) 
 *    <li>set the output vars (if any) 
 * 
 *   <li>create a ruleblock 
 *    <li>create and add rules to ruleblock 
 * </ol>
 * 
 * It is highly recommended to use the various <i>parseFrom...</i> APIs to 
 * construct rulesets, ruleblocks, and rules rather than constructing the
 * objects directly as it is easier.
 *
 * @version  $Revision: 1.4 $, $Date: 2001/09/27 20:59:15 $
 */
public class AbleRuleSetFromAPI extends Object {

   public AbleRuleSetFromAPI() {
   }

   public static void main(String[] args) {
      AbleRuleSetFromAPI test = new AbleRuleSetFromAPI();
      try {
         AbleRuleSet rs = test.test();
         
         AbleVariable in = rs.getVariable("inVar1");
         AbleVariable out = rs.getVariable("outVar1");
      
         System.out.println("done! input was "+ in.getValueString()+" and the output was "+out.getValueString());
         System.out.println("OutputBuffer[0] = "+rs.getOutputBuffer(0));
      } catch (Exception e) {
         System.out.println("Error: " + e.getLocalizedMessage());
         e.printStackTrace();
         System.exit(-1);
   }
      System.exit(0);
   }

   private AbleRuleSet test() throws AbleException {

         AbleRuleSet rs = new AbleRuleSet();

         constructRuleSet1(rs);
 
         System.out.println("Initializing the bean via init() call");
         if (rs.isExecutable()) {
            rs.init();
            rs.process();
         }
         return rs;
      }

   private void constructRuleSet1(AbleRuleSet rs) throws AbleException {

      // first set the ruleset name 
      rs.setName("ruleset1");

      // set the ruleset comment field 
      rs.setComment("this is a test ruleset");

      // now import some classes 
      rs.declareUserDataType("Vector", "java.util.Vector");
      rs.declareUserDataType("Math", "java.lang.Math");

      // now load some libraries 
      //rs.declareUserDefinedFunctionLib("com.ibm.able.rules.AbleBeanLib");

      //   To use the inner class feature, your CLASSPATH must include
      //   the jikesbt.jar, *and* the jre/lib/rt.jar from your JDK.   
      // declare an inner class ???
            Vector classVarNames = new Vector();
            classVarNames.add("fld1");
            classVarNames.add("fld2");
            Vector classVarTypes = new Vector();
            classVarTypes.add("int");
            classVarTypes.add("String");
            rs.declareInnerClass(
               "innerClass1",
               null,
               "inner class comment",
               classVarNames,
               classVarTypes);

      // now declare some variables

      //    rs.addVariable() ;    // used to add ArrayVaribles ...

      AbleVariable lclVar = null;
      lclVar = rs.declareGlobalVariable("inVar1", false, "String");
      // name, static, type
      lclVar.setInitialValue(rs.findOrCreateStringLiteral("apples"));
      lclVar = rs.declareGlobalVariable("outVar1", false, "String");
      // name, static, type
      lclVar.setInitialValue(rs.findOrCreateStringLiteral("sauce"));

      //    rs.addLocalOrGlobalVariable() ;   // used in pattern match rules 

      // now declare the inputs
      //   rs.addVariableToInputSequence("inVar1") ;

      // now declare the outputs 
      rs.addVariableToOutputSequence("outVar1");

      // now construct a ruleblock 
      AbleRuleBlock lclRuleBlock = rs.addRuleBlock("process", "void","()",new Vector(),"Script","rule block comment",new Hashtable()); 

      // now add rules to the ruleblock 

      // factory method for constructing rule piece parts 
      // theRuleTokenTypes are defined in AbleRuleSet ...   almost 40 object types 
      //   use different sets of parms depending on type of object you want to create 
      //
      // public AbleRd createRdObject(int theRuleTokenType, String theRuleToken, Vector theCallParms, AbleRd theLhs, 
      //                            String theHedges, String theFieldOrMethodName, AbleRd theIndexExpr) throws AbleParException {

      Vector lclParms = new Vector();
      lclParms.add(rs.findOrCreateStringLiteral("This is a test"));
      AbleRd lclRd =
         rs.createRdObject(
            AbleRuleSet.TokenTypeIsCallName,
            "println",
            lclParms,
            null,
            null,
            null,
            null);

      AbleAssertionClause lclAstClause =
         new AbleAssertionClause(null, AbleData.Noop, lclRd);
      AbleRule lclRule =
         new AbleAssertionRule(
            "rule1",
            new AbleDoubleLiteral(4.0),
            lclAstClause);
      // label, priority, clause
      // no rule preConditions 

      rs.addRule(lclRuleBlock, lclRule);
      AbleRule lclRule2 =
         new AbleAssertionRule(
            "rule2",
            new AbleDoubleLiteral(4.0),
            lclAstClause);
      // label, priority, clause
      rs.addRule(lclRuleBlock, lclRule2);
      lclRule.setComment("rule comment");

      //
      // parse and add a single rule to an existing ruleblock 
      //      
      String tmpRuleSource = "ruleX: if (true) then outVar1 = \"oranges\";";
      String tmpRuleBlockName = "process";
      try {
         lclRule = rs.parseRuleFromARL(tmpRuleSource, tmpRuleBlockName, false);
      } catch (Exception e) {
         System.out.println("Error " + e.toString());
      }

      //
      // parse and add a single rule to an existing ruleblock 
      //      
      tmpRuleSource = "tstRb1: invokeRuleBlock(\"postProcess\");";
      tmpRuleBlockName = "process";
      try {
         lclRule = rs.parseRuleFromARL(tmpRuleSource, tmpRuleBlockName, false);
      } catch (Exception e) {
         System.out.println("Error " + e.toString());
      }

      //
      // parse and add a single rule to an existing ruleblock 
      //      
      tmpRuleSource = "tstRb2: invokeRuleBlock(\"postProcessArml\");";
      tmpRuleBlockName = "process";
      try {
         lclRule = rs.parseRuleFromARL(tmpRuleSource, tmpRuleBlockName, false);
      } catch (Exception e) {
         System.out.println("Error " + e.toString());
      }

      //   
      // parse and add a whole ruleblock 
      //
      String tmpRuleBlockSource =
         "/** added via API parseRuleBlockFromARL */ \n void postProcess() using Script { : println(\"in postProcess\"); \n }";
      try {
         lclRuleBlock = rs.parseRuleBlockFromARL(tmpRuleBlockSource);
      } catch (Exception e) {
         System.out.println("Error " + e.toString());
      }

      //  Instantiate a single expression from AML string.
      // just shows another way to create an rd object, which could be
      // used to create an assertion rule and then added to the ruleset
      String tmpExpSource = "100.9 - 50 * 10 / 23.4";
      try {
         lclRd = rs.parseExpressionFromARL(tmpExpSource);
      } catch (Exception e) {
         System.out.println("Error " + e.toString());
      }
      System.out.println(
         "and the answer to " + ((AbleExpression) lclRd).arlCRdString() + " is "+ ((AbleExpression) lclRd).getNumericValue());

      System.out.println(rs.arlString()); // show the resulting ruleset

      //
      // parse and add a single rule to an existing ruleblock 
      //      
      String tmpRuleSourceArml =
        "<IfThenElseRule label=\"ruleY\" comment=\"\">"
        + "  <if> "
        + "    <expression>  true</expression>"
        + "  </if>"
        + "  <then>"
        + "    <action>outVar1 = &quot;peaches&quot;</action>"
        + "  </then>"
        + "  <else>"
        + "  </else>"
        + " </IfThenElseRule>";
      tmpRuleBlockName = "process";
      try {
         lclRule =
            rs.parseRuleFromARML(tmpRuleSourceArml, tmpRuleBlockName, false);
      } catch (Exception e) {
         System.out.println("Error " + e.toString());
         e.printStackTrace();
      }

      //   
      // parse and add a whole XML ruleblock 
      //
      String tmpRuleBlockSourceArml =
        "<ruleBlock name=\"postProcessArml\" returnType=\"void\" engine=\"Script\" comment=\" added via API\">"
        + "   <parameters>"
        + "   </parameters>"
        + "  <AssertionRule label=\"\" comment=\"\">"
        + "  <assert>println(&quot;in postProcessArml&quot;)</assert>"
        + "  </AssertionRule>"
        + " </ruleBlock>";
      try {
         lclRuleBlock = rs.parseRuleBlockFromARML(tmpRuleBlockSourceArml);
      } catch (Exception e) {
         System.out.println("Error " + e.toString());
      }

      //  Instantiate a single expression from XML string.
      // just shows another way to create an rd object, which could be
      // used to create an assertion rule and then added to the ruleset
      String tmpExpSourceArml =
        "<expression>"
        + "  outVar1 = \"apples\""
        + " </expression>";
      try {
         lclRd = rs.parseExpressionFromARML(tmpExpSourceArml);
      } catch (Exception e) {
         System.out.println("Error " + e.toString());
      }
      System.out.println(
         "and the answer to " + ((AbleExpression) lclRd).arlCRdString() 
            + " is " + ((AbleExpression) lclRd).getStringValue());

      System.out.println(rs.armlString()); // show the resulting xml document 
   }

}