package com.oracle.determinations.interview.engine.userplugins.autosave;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import com.oracle.determinations.engine.Attribute;
import com.oracle.determinations.engine.Entity;
import com.oracle.determinations.engine.EntityInstance;
import com.oracle.determinations.engine.Rulebase;
import com.oracle.determinations.engine.Session;
import com.oracle.determinations.interview.engine.InterviewRulebase;
import com.oracle.determinations.interview.engine.InterviewSession;
import com.oracle.determinations.interview.engine.SecurityToken;
import com.oracle.determinations.interview.engine.data.model.InterviewUserData;
import com.oracle.determinations.interview.engine.plugins.InterviewSessionPlugin;
import com.oracle.determinations.interview.engine.plugins.InterviewSessionRegisterArgs;
import com.oracle.determinations.interview.engine.plugins.data.DataAdaptorPlugin;
import com.oracle.determinations.interview.util.EngineConstants;
public class AutosaveSaver implements DataAdaptorPlugin {
// ## DEFINE VARIABLES SECTION ##
// define the driver to use
String driver = "org.apache.derby.jdbc.ClientDriver";
// the database name
String dbName="autosave";
// define the Derby connection URL to use
String connectionURL = "jdbc:derby://localhost:1527/" + dbName + ";";
Connection conn = null;
Statement s;
//Rulebase attribute to Database column mapping (there's only 1 table for this sample scenario)
static Map attributeToColumnMapping = new HashMap<String, String>();
static
{
attributeToColumnMapping.put("age", "INPUT1");
attributeToColumnMapping.put("income", "INPUT2");
attributeToColumnMapping.put("old", "OUTPUT1");
attributeToColumnMapping.put("low_income", "OUTPUT2");
attributeToColumnMapping.put("old_low_income", "OUTPUT3");
attributeToColumnMapping.put("eligible", "OUTPUT4");
}
/**
* parameter-less constructor to satisfy Plugin requirement
*/
public AutosaveSaver()
{
try {
System.out.println("-->BEFORE DRIVER IS LOADED<--");
Class.forName(driver);
System.out.println("-->AFTER DRIVER IS LOADED<--");
System.out.println(driver + " loaded. ");
} catch(java.lang.ClassNotFoundException e) {
System.err.print("ClassNotFoundException: ");
System.err.println(e.getMessage());
}
}
public InterviewSessionPlugin getInstance(InterviewSessionRegisterArgs args) {
//Demonstration of a Plugin only registering if the current rulebase is 'ExtFrameworkAutoSave'
if (args.getSession().getRulebase().getIdentifier().equals("ExtFrameworkAutoSave")){
return new AutosaveSaver();
} else {
return null;
}
}
public boolean dataAdaptorProvidesCaseID() {
return true;
}
/**
* For this scenario, the user starts from a clean Interview Session
*/
public String[] listCases(SecurityToken token, InterviewRulebase rulebase) {
return new String[0];
}
/**
* For this scenario, the user starts from a clean Interview Session
*/
public InterviewUserData load(SecurityToken token, String caseID,
InterviewRulebase rulebase) {
return null;
}
/**
* Generates a Case ID if the Case ID input arg is empty or null
*
* To perform the save, it goes through the Entities in the rulebase model data,
* then retrieves the instances of each Entity, and then goes through each instance and persists it together with its attributes.
*
* Note that saving of relationships have been left out for simplicity.
*
*/
public String save(SecurityToken token, String caseID,
InterviewSession session) {
try {
connectDBObjects();
if(caseID != null && !caseID.equals(""))
{
//Check to make sure it exists
PreparedStatement ps = conn.prepareStatement("select * from AUTOSAVE where ID=?");
ps.setString(1, caseID);
ResultSet rs = ps.executeQuery();
if(!rs.next())
{
throw new Exception("Case ID doesn't exist");
}
rs.close();
}
else
{
System.out.println("1");
System.out.println("-->statement: "+s);
//Generate the new CaseID
caseID = this.generateCaseID();
s.execute("INSERT INTO AUTOSAVE (ID) VALUES ('" + caseID + "')");
}
//Go through the Entity models
Session ruleEngineSession = session.getRuleSession();
Rulebase rulebase = ruleEngineSession.getRulebase();
List<Entity> rulebaseEntities = rulebase.getEntities();
Iterator iterateRuleEntities = rulebaseEntities.iterator();
while(iterateRuleEntities.hasNext())
{
Entity currentEntity = (Entity)iterateRuleEntities.next();
//Retrieve instances of the current Entity
Collection<EntityInstance> currentEntityInstances = currentEntity.getEntityInstances(ruleEngineSession);
Iterator iterateCurrentEntityInstances = currentEntityInstances.iterator();
while(iterateCurrentEntityInstances.hasNext())
{
EntityInstance currEntInstance = (EntityInstance)iterateCurrentEntityInstances.next();
//Persist each instance and its attributes
if(!saveNewEntityInstance(caseID, currentEntity, currEntInstance))
{
//Failed to save instance, rollback and throw a Save Failed response
throw new Exception("Save failed");
}
}
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
finally{
try {
closeDBObjects();
} catch (SQLException e) {
throw new RuntimeException(e.getMessage());
}
}
return caseID;
}
/**
* Save the Entity Instance passed in, and its attributes as a new entry.
*
* For this sample scenario - only the Global Entity is processed for simplicity
*
* @param caseID
* @param entityModel
* @param currEntInstance
* @return false if the update was unsuccessful, true if the update was successful or if there was no updates
* @throws SQLException
*/
private boolean saveNewEntityInstance(String caseID, Entity entityModel, EntityInstance currEntInstance) throws SQLException
{
if(entityModel.getName().equals(EngineConstants.GLOBAL_ENTITY_ID))
{
String updateQueryStart = "UPDATE AUTOSAVE SET ";
String updateQueryColumns = "";
String updateQueryEnd = " WHERE ID='"+caseID+"'";
//Go through the Global's attributes, and add it in the UpdateQuery
List<Attribute> entityAttributes = entityModel.getAttributes();
Iterator iterateEntityAttributes = entityAttributes.iterator();
while(iterateEntityAttributes.hasNext())
{
Attribute currentAttribute = (Attribute) iterateEntityAttributes.next();
//Gets the value of the Attribute in the entityInstance
String attributeValue = (String) currentAttribute.getFormattedValue(currEntInstance);
//Add the current Attribute's value to the Update Query if it is not empty
if(currentAttribute.getValue(currEntInstance) != null)
{
String attributeColumn = (String) attributeToColumnMapping.get(currentAttribute.getName());
updateQueryColumns += attributeColumn + "=" + "'" + attributeValue + "', ";
}
}
if(updateQueryColumns != "")
{
//Build Update Query
updateQueryColumns = updateQueryColumns.substring(0, updateQueryColumns.length()-2);//strip out the last ', '
String updateQuery = updateQueryStart + updateQueryColumns + updateQueryEnd;
if(s.executeUpdate(updateQuery) == 0)
{
return false;
}
}
}
return true;
}
private void closeDBObjects() throws SQLException {
s.close();
conn.close();
System.out.println("Closed connection");
}
private void connectDBObjects() throws SQLException {
conn = DriverManager.getConnection(connectionURL);
System.out.println("Connected to database " + dbName);
s = conn.createStatement();
}
/**
* Generates a unique case ID
*
* @return the unique case ID
*/
private String generateCaseID() {
return UUID.randomUUID().toString();
}
}