package edu.isi.karma.controller.command.selection;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import org.python.core.Py;
import org.python.core.PyCode;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.util.PythonInterpreter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import edu.isi.karma.er.helper.CloneTableUtils;
import edu.isi.karma.er.helper.PythonRepository;
import edu.isi.karma.er.helper.PythonRepositoryRegistry;
import edu.isi.karma.er.helper.PythonTransformationHelper;
import edu.isi.karma.rep.Node;
import edu.isi.karma.rep.Row;
import edu.isi.karma.rep.Table;
import edu.isi.karma.rep.Worksheet;
import edu.isi.karma.rep.Workspace;
import edu.isi.karma.webserver.ContextParametersRegistry;
import edu.isi.karma.webserver.ServletContextParameterMap;
import edu.isi.karma.webserver.ServletContextParameterMap.ContextParameter;
public class MiniSelection extends Selection {
private String pythonCode;
private boolean onError;
private static Logger logger = LoggerFactory
.getLogger(MiniSelection.class);
public MiniSelection(Workspace workspace, String worksheetId, String hTableId,
String name, String superSelectionName, String pythonCode, boolean onError) {
super(workspace, worksheetId, hTableId, name, superSelectionName);
this.pythonCode = pythonCode;
this.onError = onError;
populateSelection();
}
public void updateSelection() {
if (this.status == SelectionStatus.UP_TO_DATE)
return;
final ServletContextParameterMap contextParameters = ContextParametersRegistry.getInstance().getContextParameters(workspace.getContextId());
PythonRepository repo = PythonRepositoryRegistry.getInstance().getPythonRepository(contextParameters.getParameterValue(ContextParameter.USER_PYTHON_SCRIPTS_DIRECTORY));
PythonInterpreter interpreter = repo.getInterpreter();
repo.initializeInterpreter(interpreter);
evalColumns.clear();
String transformId = String.format("%d_%d_%s", System.currentTimeMillis(), Thread.currentThread().getId(), this.superSelectionName);
PyCode code = null;
try {
code = getCompiledCode(pythonCode, interpreter, transformId);
}catch(IOException e) {
logger.error("Code error", e);
}
for (Entry<Row, Boolean> entry : this.selectedRowsCache.entrySet()) {
Row key = entry.getKey();
entry.setValue(evaluatePythonExpression(key, code, interpreter));
}
this.status = SelectionStatus.UP_TO_DATE;
}
public void addInputColumns(String hNodeId) {
evalColumns.add(hNodeId);
}
private void populateSelection() {
final ServletContextParameterMap contextParameters = ContextParametersRegistry.getInstance().getContextParameters(workspace.getContextId());
List<Table> tables = new ArrayList<>();
Worksheet worksheet = workspace.getWorksheet(worksheetId);
CloneTableUtils.getDatatable(worksheet.getDataTable(), workspace.getFactory().getHTable(hTableId), tables, SuperSelectionManager.DEFAULT_SELECTION);
String selectionId = String.format("%d_%d_%s", System.currentTimeMillis(), Thread.currentThread().getId(), this.superSelectionName);//Thread.currentThread().getId() + this.superSelectionName;
PythonRepository repo = PythonRepositoryRegistry.getInstance().getPythonRepository(contextParameters.getParameterValue(ContextParameter.USER_PYTHON_SCRIPTS_DIRECTORY));
PythonInterpreter interpreter = repo.getInterpreter();
repo.initializeInterpreter(interpreter);
PyCode code;
try {
code = getCompiledCode(pythonCode, interpreter, selectionId);
interpreter.getLocals().__setitem__("selection", interpreter.get("selection"+selectionId));
for (Table t : tables) {
for (Row r : t.getRows(0, t.getNumRows(), SuperSelectionManager.DEFAULT_SELECTION)) {
if (code == null)
selectedRowsCache.put(r, onError);
else
selectedRowsCache.put(r, evaluatePythonExpression(r, code, interpreter));
}
}
} catch(Exception e) {
logger.error("Unable to populate selection");
}
}
private boolean evaluatePythonExpression(Row r, PyCode code, PythonInterpreter interpreter) {
evalColumns.clear();
try {
ArrayList<Node> nodes = new ArrayList<>(r.getNodes());
Node node = nodes.get(0);
interpreter.getLocals().__setitem__("nodeid", new PyString(node.getId()));
PyObject output = interpreter.eval(code);
return PythonTransformationHelper.getPyObjectValueAsBoolean(output);
}catch(Exception e) {
return onError;
}
}
private PyCode getCompiledCode(String pythonCode, PythonInterpreter interpreter, String selectionId) throws IOException {
final ServletContextParameterMap contextParameters = ContextParametersRegistry.getInstance().getContextParameters(workspace.getContextId());
String trimmedSelectionCode = pythonCode.trim();
Worksheet worksheet = workspace.getWorksheet(worksheetId);
if (trimmedSelectionCode.isEmpty()) {
trimmedSelectionCode = "return False";
}
String selectionMethodStmt = PythonTransformationHelper
.getPythonSelectionMethodDefinitionState(worksheet,
trimmedSelectionCode, selectionId);
logger.debug("Executing PySelection\n" + selectionMethodStmt);
// Prepare the Python interpreter
PythonRepository repo = PythonRepositoryRegistry.getInstance().getPythonRepository(contextParameters.getParameterValue(ContextParameter.USER_PYTHON_SCRIPTS_DIRECTORY));
repo.compileAndAddToRepositoryAndExec(interpreter, selectionMethodStmt);
PyObject locals = interpreter.getLocals();
locals.__setitem__("workspaceid", new PyString(workspace.getId()));
locals.__setitem__("selectionName", new PyString(superSelectionName));
locals.__setitem__("command", Py.java2py(this));
locals.__setitem__("worksheetId", new PyString(worksheetId));
return repo.getSelectionCode();
}
}