/* This method demonstrates how to add a Decision Table to a Rule Set
   *
   * @param   dict             An existing rules dictionary object
   * @param   shipBucketSet    An existing bucketset
   * @param   ruleset          An existing ruleset contained in the dictionary
   */
  public static void addDecisiontTableRuleToRuleset(
      RuleDictionary dict, BucketSet shipBucketSet, RuleSet ruleset) throws Exception {

    RuleSheetTable sheetTable = ruleset.getRuleSheetTable();
    RuleSheet dt = sheetTable.getByName("DecisionTable1");

    if (dt != null) {

      System.out.println("shipSurchargeRule already exists, skipping add");
    } else {

      // Add a new Rulesheet aka DecisionTable

      dt = ruleset.getRuleSheetTable().add();
      dt.setName("DecisionTable1");

      //
      // Add two dimensions aka condition rows to table
      //

      Dimension[] conditions = new Dimension[2];

      // First Row

      conditions[0] = dt.getDimensionTable().add();
      conditions[0].setValue("ItemT.productWeight");

      // Each condition must have an associated bucket set
      // In this case an existing named bucketset
      conditions[0].setSharedBucketSet(shipBucketSet);

      // Second Row

      conditions[1] = dt.getDimensionTable().add();
      conditions[1].setValue("ItemT.unitPrice.longValue()");

      // Auto create a Local bucket set for the second condition
      BucketSet bs = conditions[1].getBucketSet();
      bs.setForm(BucketSet.FORM_RANGE);
      Bucket buck = bs.add("<50");

      System.out.println("RuleTable size is " + dt.getDTRuleTable().size());

      // Add an Action for the decision table
      // A DTAction is an action that may be selected by any rule in the decision table,
      // optionally with different parameters per rule.
      // An ExpressionTable entry is created when an Action Form property is set so that it has the
      // correct
      // number and type of parameters. ExpressionTable Rows cannot be directly added, deleted, or
      // moved.

      DTAction dtAction = dt.getDTActionTable().add();
      dtAction.setForm(Action.FORM_MODIFY);
      dtAction.setTarget("ItemT");

      // Set the target expression as a decision table action parameter
      Expression surchargeExpr = dtAction.getExpressionByParameterAlias("shipSurcharge");

      // If each rule wants to set a different action value then the DTAction value shoudl be
      // parameterized,
      // then each rule DTActionNode receives a dynamic copy of the expression (parameter table)
      surchargeExpr.setDTActionParameterName("shipSurcharge");

      // set a value for all rules, or a default value if parameterized
      surchargeExpr.setValue("10.0");

      // An initial default rule is added to the Decision Table when a dimension is added to the
      // decision table
      // The default rule has no dimensions set.
      // If we remove the initial rule, it also removes all dimensions from the DimensionTable
      // The default rule must have its dimensions set before canAdd() will be true and more rules
      // can be added to the rule table
      // The canAdd() method on the RuleTable indicates whether a new rule can be added
      // New rules can only be added to the rule table if all the existing rules in the  table have
      // dimensions specified.
      // Also if two rules are added with identical condition values, the second add is ignored

      System.out.println("Rules can be added? " + dt.getDTRuleTable().canAdd());
      DTRule dtRuleDef = dt.getDTRuleTable().get(0);

      dtRuleDef.getDimensionNode(0).setValues("otherwise");
      dtRuleDef.getDimensionNode(1).setValues(">=50");

      if (!updateRuleDictionary(dict)) System.out.println("UNABLE to update dictionary.");
      else System.out.println("Updated dictionary");

      // Next add more rules to the table, 1 for each value in the ship bucket set productWeight

      BucketSet bucketSet = conditions[0].getBucketSet();
      List<Bucket> bcks = bucketSet.getBuckets();

      for (int i = 1;
          i < bcks.size() - 1;
          i++) // skip the first bucket value handled by the default rule
      {
        System.out.println("Rules can be added " + dt.getDTRuleTable().canAdd());
        DTRule dtRule =
            dt.getDTRuleTable().add(); // use returned rule, cannot use rule returned by .get(i) ?
        System.out.println("Added new rule");

        // Set the dimension/condition values for the new rule
        dtRule.getDimensionNode(0).setValues(bcks.get(i).getName()); // "Heavy, Very Light etc"
        dtRule.getDimensionNode(1).setValues(">=50");

        // An update is required here so a DTActionNode Expression table entry for the new rule will
        // be created.
        // If an expression parameter in the DTAction exists, then the expression is copied from the
        // DTActionNode of the new Rule.
        // A value for the parameter will be added later after the update

        if (!updateRuleDictionary(dict)) System.out.println("UNABLE to update dictionary.");
        else System.out.println("Updated dictionary");
      }

      // Loop again and set the parmameter values for each rule expression
      for (int i = 1;
          i < bcks.size() - 1;
          i++) // skip the first bucket value handled by the default rule
      {
        DTRule dtRuleDef1 = dt.getDTRuleTable().get(i);

        Expression expr =
            dtRuleDef1.getDTActionNode(0).getExpressionByDTActionParameterName("shipSurcharge");
        // Estimate a cost
        if (expr != null) expr.setValue(Double.toString(i * 15.00));
      }

      System.out.println("Rule table now contains " + dt.getDTRuleTable().size() + " rules");

      if (!updateRuleDictionary(dict)) System.out.println("UNABLE to update dictionary.");
      else System.out.println("Updated dictionary");
    }
  }
  public static void addDecisiontTableRuleToRuleset(
      RuleDictionary dict, BucketSet ageBucketSet, RuleSet ruleset) throws Exception {

    RuleSheetTable sheetTable = ruleset.getRuleSheetTable();
    RuleSheet dt = sheetTable.getByName("Proposal");

    if (dt != null) {
      System.out.println("Proposal already exists, skipping add");
    } else {
      // Add a new Rulesheet aka DecisionTable
      dt = ruleset.getRuleSheetTable().add();
      dt.setName("Proposal");

      // Add two dimensions aka condition rows to table
      Dimension[] conditions = new Dimension[2];

      // First Row
      conditions[0] = dt.getDimensionTable().add();
      conditions[0].setValue("Person.age");
      conditions[0].setSharedBucketSet(ageBucketSet);

      // Second Row
      conditions[1] = dt.getDimensionTable().add();
      conditions[1].setValue("Person.policy_type");
      conditions[1].setSharedBucketSetByAlias("Person$PolicyType");

      System.out.println("RuleTable size is " + dt.getDTRuleTable().size());

      DTAction dtAction = dt.getDTActionTable().add();
      dtAction.setForm(Action.FORM_ASSERT_NEW);
      dtAction.setTarget("Product");
      dtAction.setAlwaysSelected(true);

      Expression assertExp = dtAction.getExpressionByParameterAlias("name");
      assertExp.setDTActionParameterName("name");
      assertExp.setValue("\"PROD_TYPE1\"");

      System.out.println("1. Rules can be added? " + dt.getDTRuleTable().canAdd());
      DTRule dtRuleDef = dt.getDTRuleTable().get(0);

      dtRuleDef.getDimensionNode(0).setValues("Minor");
      dtRuleDef.getDimensionNode(1).setValues("INDIVIDUAL");

      if (!RuleUtil.updateRuleDictionary(dict)) {
        System.out.println("Dictionary update failed.");
      } else {
        System.out.println("Updated dictionary");
      }

      // 2 ---------------------------------------------
      System.out.println("2. Rules can be added? " + dt.getDTRuleTable().canAdd());
      DTRule dtRuleDef1 = dt.getDTRuleTable().add();
      dtRuleDef1.getDimensionNode(0).setValues("Junior");
      dtRuleDef1.getDimensionNode(1).setValues("GROUP");

      if (!RuleUtil.updateRuleDictionary(dict)) {
        System.out.println("Dictionary update failed.");
      } else {
        System.out.println("Updated dictionary");
      }

      Expression expr = dtRuleDef1.getDTActionNode(0).getExpressionByDTActionParameterName("name");
      dtRuleDef1.getDTActionNode(0).setActionSelected(true);
      if (expr != null) {
        expr.setValue("\"PROD_TYPE2\"");
      }

      // 3 ---------------------------------------------
      System.out.println("3. Rules can be added? " + dt.getDTRuleTable().canAdd());
      DTRule dtRuleDef3 = dt.getDTRuleTable().add();
      dtRuleDef3.getDimensionNode(0).setValues("Middle");
      dtRuleDef3.getDimensionNode(1).setValues("INDIVIDUAL");

      if (!RuleUtil.updateRuleDictionary(dict)) {
        System.out.println("UNABLE to update dictionary.");
      } else {
        System.out.println("Updated dictionary");
      }

      Expression expr3 = dtRuleDef3.getDTActionNode(0).getExpressionByDTActionParameterName("name");
      dtRuleDef3.getDTActionNode(0).setActionSelected(true);
      if (expr3 != null) {
        expr3.setValue("\"PROD_TYPE3\"");
      }

      // 4 ---------------------------------------------
      System.out.println("4. Rules can be added? " + dt.getDTRuleTable().canAdd());
      DTRule dtRuleDef4 = dt.getDTRuleTable().add();
      dtRuleDef4.getDimensionNode(0).setValues("Senior");
      dtRuleDef4.getDimensionNode(1).setValues("GROUP");

      if (!RuleUtil.updateRuleDictionary(dict)) {
        System.out.println("Dictionary update failed.");
      } else {
        System.out.println("Updated dictionary");
      }

      Expression expr4 = dtRuleDef4.getDTActionNode(0).getExpressionByDTActionParameterName("name");
      dtRuleDef4.getDTActionNode(0).setActionSelected(true);
      if (expr4 != null) {
        expr4.setValue("\"PROD_TYPE4\"");
      }

      // 5 ---------------------------------------------
      System.out.println("5. Rules can be added? " + dt.getDTRuleTable().canAdd());
      DTRule dtRuleDef5 = dt.getDTRuleTable().add();
      dtRuleDef5.getDimensionNode(0).setValues("Senior");
      dtRuleDef5.getDimensionNode(1).setValues("UNKNOWN");

      if (!RuleUtil.updateRuleDictionary(dict)) {
        System.out.println("Dictionary update failed.");
      } else {
        System.out.println("Updated dictionary");
      }

      Expression expr5 = dtRuleDef5.getDTActionNode(0).getExpressionByDTActionParameterName("name");
      dtRuleDef5.getDTActionNode(0).setActionSelected(true);
      if (expr5 != null) {
        expr5.setValue("\"PROD_TYPE0\"");
      }

      System.out.println("Rule table now contains " + dt.getDTRuleTable().size() + " rules");
    }
  }