package edu.isi.karma.controller.history;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import edu.isi.karma.controller.command.Command;
import edu.isi.karma.controller.command.Command.CommandTag;
import edu.isi.karma.controller.command.CommandException;
import edu.isi.karma.controller.command.CommandFactory;
import edu.isi.karma.controller.command.JSONInputCommandFactory;
import edu.isi.karma.controller.history.CommandHistoryWriter.HistoryArguments;
import edu.isi.karma.controller.history.HistoryJsonUtil.ClientJsonKeys;
import edu.isi.karma.controller.history.HistoryJsonUtil.ParameterType;
import edu.isi.karma.rep.HNode;
import edu.isi.karma.rep.HTable;
import edu.isi.karma.util.JSONUtil;
import edu.isi.karma.view.VWorkspace;
import edu.isi.karma.webserver.ExecutionController;
import edu.isi.karma.webserver.KarmaException;
import edu.isi.karma.webserver.WorkspaceRegistry;
public class WorksheetCommandHistoryReader {
private final String vWorksheetId;
private final VWorkspace vWorkspace;
private static Logger logger = LoggerFactory.getLogger(WorksheetCommandHistoryReader.class);
public WorksheetCommandHistoryReader(String vWorksheetId, VWorkspace vWorkspace) {
super();
this.vWorksheetId = vWorksheetId;
this.vWorkspace = vWorkspace;
}
public HashMap<CommandTag, Integer> readAndExecuteCommands(List<CommandTag> tags)
throws FileNotFoundException, JSONException, KarmaException, CommandException {
String worksheetName = vWorkspace.getViewFactory().getVWorksheet(vWorksheetId).getWorksheet().getTitle();
File historyFile = new File(HistoryJsonUtil.constructWorksheetHistoryJsonFilePath(worksheetName, vWorkspace.getPreferencesId()));
JSONArray historyJson = (JSONArray) JSONUtil.createJson(new FileReader(historyFile));
ExecutionController ctrl = WorkspaceRegistry.getInstance().getExecutionController(vWorkspace.getWorkspace().getId());
HashMap<String, CommandFactory> commandFactoryMap = ctrl.getCommandFactoryMap();
HashMap<CommandTag, Integer> commandsExecutedCountByTag = new HashMap<Command.CommandTag, Integer>();
for (CommandTag tag: tags) {
commandsExecutedCountByTag.put(tag, 0);
}
for (int i = 0; i< historyJson.length(); i++) {
JSONObject commObject = (JSONObject) historyJson.get(i);
JSONArray commandTags = commObject.getJSONArray(HistoryArguments.tags.name());
for (int j=0; j<commandTags.length(); j++) {
CommandTag tag = CommandTag.valueOf(commandTags.getString(j));
if(tags.contains(tag)) {
executeCommand(commObject, commandFactoryMap);
commandsExecutedCountByTag.put(tag, commandsExecutedCountByTag.get(tag).intValue()+1);
break;
}
}
}
return commandsExecutedCountByTag;
}
public void readAndExecuteAllCommandsFromFile(File historyFile)
throws JSONException, KarmaException, CommandException, FileNotFoundException {
JSONArray historyJson = (JSONArray) JSONUtil.createJson(new FileReader(historyFile));
readAndExecuteAllCommands(historyJson);
}
public void readAndExecuteAllCommands(JSONArray historyJson)
throws JSONException, KarmaException, CommandException {
ExecutionController ctrl = WorkspaceRegistry.getInstance().getExecutionController(vWorkspace.getWorkspace().getId());
HashMap<String, CommandFactory> commandFactoryMap = ctrl.getCommandFactoryMap();
for (int i = 0; i< historyJson.length(); i++) {
JSONObject commObject = (JSONObject) historyJson.get(i);
executeCommand(commObject, commandFactoryMap);
}
}
public void executeListOfCommands(List<String> commandsJsonList) throws JSONException, KarmaException, CommandException {
ExecutionController ctrl = WorkspaceRegistry.getInstance().getExecutionController(vWorkspace.getWorkspace().getId());
HashMap<String, CommandFactory> commandFactoryMap = ctrl.getCommandFactoryMap();
for(String commJson : commandsJsonList) {
JSONObject commObject = new JSONObject(commJson);
executeCommand(commObject, commandFactoryMap);
}
}
private void executeCommand(JSONObject commObject, HashMap<String, CommandFactory> commandFactoryMap)
throws JSONException, KarmaException, CommandException {
JSONArray inputParamArr = (JSONArray) commObject.get(HistoryArguments.inputParameters.name());
logger.info("Command in history: " + commObject.get(HistoryArguments.commandName.name()));
// Change the hNode ids, vworksheet id to point to the current worksheet ids
if(normalizeCommandHistoryJsonInput(vWorkspace, vWorksheetId, inputParamArr)) {
// Invoke the command
CommandFactory cf = commandFactoryMap.get(commObject.get(HistoryArguments.commandName.name()));
if(cf != null && cf instanceof JSONInputCommandFactory) {
// logger.info("Executing command from history: " + commObject.get(HistoryArguments.commandName.name()));
JSONInputCommandFactory scf = (JSONInputCommandFactory)cf;
Command comm = scf.createCommand(inputParamArr, vWorkspace);
if(comm != null){
// logger.info("Executing command: " + commObject.get(HistoryArguments.commandName.name()));
vWorkspace.getWorkspace().getCommandHistory().doCommand(comm, vWorkspace);
}
else
logger.error("Error occured while creating command (Could not create Command object): "
+ commObject.get(HistoryArguments.commandName.name()));
}
}
}
public List<String> getJSONForCommands(CommandTag tag) {
List<String> commandsJSON = new ArrayList<String>();
String worksheetName = vWorkspace.getViewFactory().getVWorksheet(vWorksheetId).getWorksheet().getTitle();
File historyFile = new File(HistoryJsonUtil.constructWorksheetHistoryJsonFilePath(worksheetName, vWorkspace.getPreferencesId()));
try {
JSONArray historyJson = (JSONArray) JSONUtil.createJson(new FileReader(historyFile));
for (int i = 0; i< historyJson.length(); i++) {
JSONObject commObject = (JSONObject) historyJson.get(i);
JSONArray tags = commObject.getJSONArray(HistoryArguments.tags.name());
for (int j=0; j< tags.length(); j++) {
String tag2 = tags.getString(j);
if(tag2.equals(tag.name()))
commandsJSON.add(commObject.toString());
}
}
} catch (FileNotFoundException e) {
logger.error("History file not found!", e);
return commandsJSON;
} catch (JSONException e) {
logger.error("Error occured while working with JSON!", e);
}
return commandsJSON;
}
public static boolean normalizeCommandHistoryJsonInput(VWorkspace vWorkspace, String vWorksheetId,
JSONArray inputArr) throws JSONException {
HTable hTable = vWorkspace.getViewFactory().getVWorksheet(vWorksheetId).getWorksheet().getHeaders();
for (int i = 0; i < inputArr.length(); i++) {
JSONObject inpP = inputArr.getJSONObject(i);
/*** Check the input parameter type and accordingly make changes ***/
if(HistoryJsonUtil.getParameterType(inpP) == ParameterType.hNodeId) {
JSONArray hNodeJSONRep = new JSONArray(inpP.getString(ClientJsonKeys.value.name()));
for (int j=0; j<hNodeJSONRep.length(); j++) {
JSONObject cNameObj = (JSONObject) hNodeJSONRep.get(j);
if(hTable == null) {
logger.error("null HTable while normalizing JSON input for the command.");
return false;
}
logger.debug("Column being normalized: "+ cNameObj.getString("columnName"));
HNode node = hTable.getHNodeFromColumnName(cNameObj.getString("columnName"));
if(node == null) {
logger.error("null HNode while normalizing JSON input for the command.");
return false;
}
if (j == hNodeJSONRep.length()-1) { // Found!
inpP.put(ClientJsonKeys.value.name(), node.getId());
hTable = vWorkspace.getViewFactory().getVWorksheet(vWorksheetId).
getWorksheet().getHeaders();
} else {
hTable = node.getNestedTable();
}
}
} else if(HistoryJsonUtil.getParameterType(inpP) == ParameterType.vWorksheetId) {
inpP.put(ClientJsonKeys.value.name(), vWorksheetId);
}
}
return true;
}
}