// Copyright (c) 2001, 2003, Oracle Corporation.  All rights reserved.  
// File: ARDemo.java

/**
 * This sample program describes how to use the ODM Java API to build
 * an AssociationRules (AR) model and show how to extract association rules
 * from the model.
 * 
 * This program uses the "MARKET_BASKET_V" dataset.
 * 
 * NOTE:
 *   Before executing this program you need to provide DB URL, username 
 *   and password in login method and a valid data schema name
 *   by changing the DATA_SCHEMA_NAME constant value in the program.
 */

// Generic Java Imports
import java.io.*;
import java.util.*;
import java.sql.SQLException;

// ODM Imports
import oracle.dmt.odm.*;
import oracle.dmt.odm.data.*;
import oracle.dmt.odm.settings.function.*;
import oracle.dmt.odm.settings.algorithm.*;
import oracle.dmt.odm.task.*;
import oracle.dmt.odm.model.*;
import oracle.dmt.odm.result.*;
import oracle.dmt.odm.rule.*;

public class ARDemo extends Object
{
  private static DataMiningServer m_dms = null;
  private static oracle.dmt.odm.Connection m_dmsConn = null;
  private static final String DATA_SCHEMA_NAME = "schema name";

  public static void main( String args[] ) { 
    try {      
      //1. Login to the Data Mining Server
      //Create a DMS object
      m_dms = new DataMiningServer(
            "put DB URL here", //JDBC URL jdbc:oracle:thin:@<Host name>:<Port>:<SID>
            "user name", //User Name
            "password" //Password 
          );
      //Login to the DMS and create a DMS Connection
      m_dmsConn = m_dms.login();
      //Remove the objects to avoid name conflicts
      cleanup();
      //2. Build an AR model
      buildModel();
      //3. Extract association rules from the model
      retrieveAssociationRules();
    } catch(Exception anyExp) {
      anyExp.printStackTrace(System.out);
    } finally {
      try {
        //6. Logout from the Data Mining Server
        m_dms.logout(m_dmsConn);
      } catch(Exception anyExp1) { }//Ignore
    }
  }

  /**
   * Build operation is performed by a task that requires the location of
   * the dataset, a mining function settings and the model name.
   * In this example, an AssociationRules (AR) model "ARDemo_Model" is built
   * using the dataset "MARKET_BASKET_2D_BINNED" by the default AR algorithm.
   * This model will be used to show how to extract association rules.
   */
  public static boolean buildModel()
    throws ODMException, SQLException, IOException 
  {
    boolean isTaskSuccess = false;
    //1. Create PhysicalDataSpecification for build
    LocationAccessData lad = new LocationAccessData( 
                  "MARKET_BASKET_V",        //Data Table Name
                  DATA_SCHEMA_NAME          //Schema Name
                  );
    PhysicalDataSpecification pds = new NonTransactionalDataSpecification(lad);
    //2. Create & Store Mining Function Settings
    AssociationRulesFunctionSettings armfs =
          AssociationRulesFunctionSettings.create(
                  m_dmsConn,        //DMS Connection
                  pds,              //Build data specification
                  DataPreparationStatus.unprepared, //Default preparation status
                  0.01f,            //Minimum support
                  0.9f,             //Minimum confidence
                  5                 //Maximum rule length
          );
    //3. Set inactive attributes by changing the default attribute usage
    armfs.adjustAttributeUsage(
                  new String[] {"CUST_ID"}, AttributeUsage.inactive);
    armfs.store(m_dmsConn, "ARDemo_MFS");
    //4. Create, store & execute Build Task
    MiningBuildTask arBuildTask = new MiningBuildTask(
                  pds,            //Build data specification
                  "ARDemo_MFS",   //Mining function settings name
                  "ARDemo_Model"  //Mining model name
                  );
    arBuildTask.store(m_dmsConn, "ARDemo_Model_BuildTask"); //Store the task
    arBuildTask.execute(m_dmsConn); //Execute the task asynchronously
    System.out.print("ARDemo_Model_BuildTask is started, please wait. ");
    //5. Wait for completion of the task
    MiningTaskStatus arBuildStatus = arBuildTask.waitForCompletion(m_dmsConn);
    //6. Check the status of the task after completion
    isTaskSuccess = arBuildStatus.getTaskState().equals(MiningTaskState.success);
    if( isTaskSuccess )
      //Task completed successfully
      System.out.println( "ARDemo_Model built successfully.");
    else { //Task failed
      throw new ODMException("ARDemo_Model build failed.\nFailure description: "
                          + arBuildStatus.getStateDescription() );
    }
    return isTaskSuccess;
  }

  public static void retrieveAssociationRules()
    throws ODMException, MiningObjectException, SQLException
  {
    MiningRuleSet ruleSet = null;
    //1. Get rules by a number.
    System.out.println("3 rules with highest support:");
    ruleSet = AssociationRulesModel.getRules(
                m_dmsConn,
                "ARDemo_Model",
                3, // Maximum number of rules to be retrieved.
                RuleSortCriteria.support); // Rules sorted by support
    printRules(ruleSet);    //Print the rules
    //2. Get rules by support.
    System.out.println("3 rules with support of 0.02 or higher:");
    ruleSet = AssociationRulesModel.getRules(
                m_dmsConn,                // connection to DMS
                "ARDemo_Model",           // the AR model name
                RuleSortCriteria.support, // for support
                ComparisonFunction.ge,    // greater than or equal
                (float) 0.02,             // to 2%
                new RuleSortCriteria[] { RuleSortCriteria.support },
                new SortOrder[] { SortOrder.descending },
                3 );                      // maximum number of rules
    printRules(ruleSet);    // Print the rules
    //3. Get rules by confidence.
    System.out.println("3 rules with confidence of 0.9 or higher:");
    ruleSet = AssociationRulesModel.getRules(
                m_dmsConn,                  // connection to DMS
                "ARDemo_Model",             // the AR model name
                RuleSortCriteria.confidence,// for confidence
                ComparisonFunction.ge,      // greater than or equal
                (float) 0.9,                // to 90%
                new RuleSortCriteria[] { RuleSortCriteria.confidence },
                new SortOrder[] { SortOrder.descending },
                3 );                        // maximum number of rules
    printRules(ruleSet);    // Print the rules
    //4. Get rules with specified antecedent and consequent.
    System.out.println("3 rules with specified antecedents and consequents:");
    String[] ante = new String[] { "FLAT_PANEL_MONITOR", "EXTENSION_CABLE"};
    String[] cons = new String[] { "MOUSE_PAD" };
    ruleSet = AssociationRulesModel.getRulesByContents(
                m_dmsConn,
                "ARDemo_Model",
                ante,
                cons,
                RuleSortCriteria.support, // where the support is
                ComparisonFunction.ge,    // greater than or equal to
                0.01f,                    // 1%
                new RuleSortCriteria[]    // order by rule length and support
                    { RuleSortCriteria.ruleLength, RuleSortCriteria.support },
                null,       // default sort order for each criterion
                3 );        // Maximum number of rules to be retrieved
    printRules(ruleSet);    // Print the rules
  }
  
  /**
   * Cleanup the previously created objects if any. 
   */
  private static void printRules(MiningRuleSet ruleSet)
    throws SQLException, MiningObjectException, ODMException
  {
    for( int i=0; i<ruleSet.getNumberOfRules(); i++ ) {
      MiningRule arRule = ruleSet.getNextRule();
      System.out.println(arRule.toString());
    }
    // The rule set must be closed after use.
    ruleSet.close();
  }

  /**
   * Cleanup the previously created objects if any. 
   */
  private static void cleanup() throws ODMException, SQLException
  {
    //Remove the function settings
    try {
      AssociationRulesFunctionSettings.remove(m_dmsConn, "ARDemo_MFS");
    }catch(Exception anyExp1) { }//Ignore
    //Remove the task
    try {
      MiningBuildTask.remove(m_dmsConn, "ARDemo_Model_BuildTask");
    }catch(Exception anyExp1) { }//Ignore
    //Remove the model
    try {
      MiningModel.remove(m_dmsConn, "ARDemo_Model");
    }catch(Exception anyExp1) { }//Ignore
  }
}
