/* This method demonstrates how to add a new BucketSet to a dictionary data model
   *
   * @param   dict             An existing rules dictionary object
   */
  public static BucketSet addBucketSet(RuleDictionary dictionary) throws Exception {

    DataModel model = dictionary.getDataModel();

    // Create a new bucketset holding product weight descriptions
    BucketSetTable bucketSetTable = model.getBucketSetTable();

    BucketSet productWeightBucketSet = bucketSetTable.getByName("ShipWeightType");

    if (productWeightBucketSet != null) {

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

      productWeightBucketSet = bucketSetTable.add();
      productWeightBucketSet.setName("ShipWeightType");
      productWeightBucketSet.setForm(BucketSet.FORM_LOV);
      productWeightBucketSet.add("Light");
      productWeightBucketSet.add("Heavy");
      productWeightBucketSet.add("VeryHeavy");
    }
    return productWeightBucketSet;
  }
  public static BucketSet addAgeBucketSet(RuleDictionary dictionary) throws Exception {
    DataModel model = dictionary.getDataModel();

    // Create a new bucketset holding product weight descriptions
    BucketSetTable bucketSetTable = model.getBucketSetTable();
    BucketSet ageBucketSet = bucketSetTable.getByName("Age");

    if (ageBucketSet != null) {
      System.out.println("Age BucketSet already exists, skipping add");
    } else {
      ageBucketSet = bucketSetTable.add();
      ageBucketSet.setName("Age");
      ageBucketSet.setForm(BucketSet.FORM_RANGE);
      ageBucketSet.setType("int");

      ageBucketSet.add("<0").setAlias("Minor");
      ageBucketSet.add("<18").setAlias("Junior");
      ageBucketSet.add("<50").setAlias("Middle");
      ageBucketSet.add("<75").setAlias("Senior");
    }
    return ageBucketSet;
  }
  /* 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");
    }
  }