
prerna.sablecc2.translations.OptimizeRecipeTranslation Maven / Gradle / Ivy
The newest version!
package prerna.sablecc2.translations;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PushbackReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import prerna.om.Insight;
import prerna.reactor.IReactor;
import prerna.reactor.insights.SetInsightGoldenLayoutReactor;
import prerna.reactor.map.MapListReactor;
import prerna.reactor.map.MapReactor;
import prerna.sablecc2.PixelPreProcessor;
import prerna.sablecc2.PixelUtility;
import prerna.sablecc2.analysis.DepthFirstAdapter;
import prerna.sablecc2.lexer.Lexer;
import prerna.sablecc2.lexer.LexerException;
import prerna.sablecc2.node.ABooleanScalar;
import prerna.sablecc2.node.AFractionDecimal;
import prerna.sablecc2.node.AMap;
import prerna.sablecc2.node.AMapList;
import prerna.sablecc2.node.AMapNegNum;
import prerna.sablecc2.node.AMapVar;
import prerna.sablecc2.node.ANoun;
import prerna.sablecc2.node.ANounOpInput;
import prerna.sablecc2.node.ANullScalar;
import prerna.sablecc2.node.AOperation;
import prerna.sablecc2.node.ARoutineConfiguration;
import prerna.sablecc2.node.AScalarRegTerm;
import prerna.sablecc2.node.AWholeDecimal;
import prerna.sablecc2.node.AWordMapKey;
import prerna.sablecc2.node.AWordWordOrId;
import prerna.sablecc2.node.POpInput;
import prerna.sablecc2.node.POtherOpInput;
import prerna.sablecc2.node.PRoutine;
import prerna.sablecc2.node.Start;
import prerna.sablecc2.om.GenRowStruct;
import prerna.sablecc2.om.PixelDataType;
import prerna.sablecc2.om.ReactorKeysEnum;
import prerna.sablecc2.om.nounmeta.NounMetadata;
import prerna.sablecc2.om.task.options.TaskOptions;
import prerna.sablecc2.parser.Parser;
import prerna.sablecc2.parser.ParserException;
import prerna.util.Constants;
import prerna.util.Utility;
import prerna.util.insight.InsightUtility;
public class OptimizeRecipeTranslation extends DepthFirstAdapter {
// create logger
private static final Logger logger = LogManager.getLogger(OptimizeRecipeTranslation.class.getName());
// set of reactors that send back task data to visualize
private static Set taskReactors = new HashSet();
static {
taskReactors.add("RunNumericalCorrelation");
taskReactors.add("RunMatrixRegression");
taskReactors.add("RunClassification");
taskReactors.add("GetRFResults");
taskReactors.add("RunAssociatedLearning");
taskReactors.add("NodeDetails");
}
// set of reactors that are used to send back ornaments w/ a task to a panel
private static Set taskOrnamentReactors = new HashSet();
static {
taskOrnamentReactors.add("RetrievePanelColorByValue");
}
// need to keep the reactors for proper parsing of maps
private boolean captureMap = false;
private IReactor curReactor = null;
// gson variable
private static Gson gson = new GsonBuilder().disableHtmlEscaping().create();
// keep track of the index of expressions
private int index = 0;
// map the index to the expressions
private HashMap expressionMap = new HashMap();
// list to maintain what sheets exist
private List sheetList = new Vector();
// keep order of panel creation
private List panelCreationOrder = new ArrayList();
// panelMap will keep track of the panelId -> list of expressions in order of occurrence
// "0" -> [0,1,3] means that panel zero occurred in the TaskOptions of expressions 0, 1 and 3
private HashMap> panelMap = new HashMap>();
// layerMap will keep track of the panelId -> layer -> list of expressions in order of occurence
private HashMap>> layerMap = new HashMap>>();
// panelOrnamentMap will track panelId -> list of expressions in order of occurrence
// "0" -> [5.6] means that panel zero has these panel ornament tasks that need to be tracked
private HashMap> panelOrnamentMap = new HashMap>();
// keep a list of the expressions to keep
// we will add all expressions with no TaskOptions and then add the expressions that we do need with the task options
// we will order it at the end
private List optimizedRecipeIndicesToKeep = new ArrayList();
// we need to keep track of whether each expression contained TaskOptions
// create a variable that will be reset for each expression to indicate whether or not we encountered an instance of TaskOptions
// this is needed because if we get through a whole expression without hitting TaskOptions then we want to go ahead and add it to expressionsToKeep
private boolean containsTaskOptions = false;
private boolean containsOrnamentTaskOptions = false;
private boolean containsPanelKey = false;
// need to account for clones
// so grab the most recent Panel() value
// in case a clone comes afterwards
private String curPanelId = null;
private Map clonePanelToOrigPanel = new HashMap();
private Map cloneToOrigTask = new HashMap();
private Map cloneIndexToClonePanelId = new HashMap();
private Map cloneIdToIndex = new HashMap();
// need to keep track
// of the panel view modifications performed
// so that we know when a panel clone was necessary
private Map> panelToPanelView = new HashMap>();
// create a variable to keep track of the current mapping of the original expression to the encoded expression
public HashMap encodedToOriginal = new HashMap();
public List encodingList = new Vector();
// just aggregate all the remove layer indices for now
private List removeLayerIndices = new Vector();
private Map> lastRemovePanelLayerMap = new HashMap<>();
private Map insightConfig = null;
/**
* This method overrides caseAConfiguration, adds each expression to the expressionMap, adds expression indexes to the expression map, and updates the index
*
* @param node
*/
@Override
public void caseARoutineConfiguration(ARoutineConfiguration node) {
List copy = new ArrayList(node.getRoutine());
for(PRoutine e : copy) {
// for each expression, reset whether it contains TaskOptions
// default to false and change to true if we hit TaskOptions within the expression
curPanelId = null;
containsTaskOptions = false;
containsOrnamentTaskOptions = false;
String expression = e.toString();
// add the expression to the map
//when we put the expression in the expression map, this is when we should change to the unencoded version
expression = PixelUtility.recreateOriginalPixelExpression(expression, encodingList, encodedToOriginal);
expressionMap.put(index, expression);
logger.info("Processing " + Utility.cleanLogString(expression) + "at index: " + index);
e.apply(this);
// if we made it through all reactors of the expression without ever hitting TaskOptions, go ahead and add the expression to expressionsToKeep
// this is run for each expression
if (!containsTaskOptions && !containsOrnamentTaskOptions) {
optimizedRecipeIndicesToKeep.add(index);
}
// increase the index for each expression
index++;
}
}
/**
* This method overrides inAOperation and determines the actions to take based on the reactor (TaskOptions and ClosePanel reactors)
*
* @param node
*/
@Override
public void inAOperation(AOperation node) {
defaultIn(node);
// check to see if the reactor is TaskOptions by getting the reactorId
String reactorId = node.getId().toString().trim();
// if the reactor is TaskOptions, we need to know the panel
if (reactorId.equals("TaskOptions")) {
// go ahead and set containsTaskOptions to true
containsTaskOptions = true;
// input is the whole input to TaskOptions
POpInput input = node.getOpInput();
String inputMapString = input.toString();
// convert the inputMapString to a map
Map inputMap = null;
try {
inputMap = gson.fromJson(inputMapString, Map.class);
} catch (Exception e2) {
throw new IllegalArgumentException("Unable to cast TaskOptions into a map");
}
// create a TaskOptions object from the map
// this will allow us to get the panel id
TaskOptions ops = new TaskOptions(inputMap);
// it is possible that we have more than panel id passed into TaskOptions
// the panel ids are stored as a set of strings
Set panelId = ops.getPanelIds();
// we now have a set of panel ids
// we need to make sure that each of the panel ids is included in panelMap with the associated expression index
// for each panel in the set of panel ids
for (String panel : panelId) {
addPanelForCurrentIndex(panel);
// when we run a task - we automatically set the current panel to visualization
addPanelView(panel, InsightUtility.PANEL_VIEW_VISUALIZATION);
Map thisPanelOptions = (Map) inputMap.get(panel);
if(thisPanelOptions == null) {
// try casting to integer
// annoying...
try {
thisPanelOptions = (Map) inputMap.get( Integer.parseInt(panel) + "");
} catch(Exception e) {
//ignore
}
}
if(thisPanelOptions != null && thisPanelOptions.containsKey("layer")) {
Map layerMap = (Map) thisPanelOptions.get("layer");
String layerId = (String) layerMap.get("id");
addLayerForCurrentIndex(panel, layerId);
} else {
addLayerForCurrentIndex(panel, "0");
}
}
} else if (reactorId.equals("ClosePanel")) {
// if we close the panel, then we can get rid of the places we had TaskOptions for that panel
// the TaskOptions so far are kept track of in panel map
// first, grab the input from the ClosePanel reactor
POpInput closePanelInput = node.getOpInput();
String closePanelId = closePanelInput.toString().trim();
// we now have the panel id of the closed panel
// look at the current panel map and see if that key exists
if (panelMap.containsKey(closePanelId)) {
// if it exists, then remove it, we don't need any of these expressions
panelMap.remove(closePanelId);
}
// same with panel to panel view map
if (this.panelToPanelView.containsKey(closePanelId)) {
this.panelToPanelView.remove(closePanelId);
}
// remove the panel that was created
if (panelCreationOrder.contains(closePanelId)) {
panelCreationOrder.remove(closePanelId);
}
// remove the panel from the layer logic as well
if (layerMap.containsKey(closePanelId)) {
layerMap.remove(closePanelId);
}
} else if(reactorId.equals("Panel")) {
// this is in case there is a clone that is coming up
POpInput input = node.getOpInput();
this.curPanelId = input.toString().trim();
this.curPanelId = trimQuotes(this.curPanelId);
}
else if (reactorId.equals("Clone")) {
String panelId = this.curPanelId;
String clonePanelId = null;
String sheet = null;
POpInput closePanelInput = node.getOpInput();
if(closePanelInput instanceof ANounOpInput) {
// see if this starts with panel = [
String strI = closePanelInput.toString();
if(strI.startsWith("panel = [")) {
strI = strI.substring("panel = [ ".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
panelId = strI;
} else if(strI.startsWith("cloneId = [")) {
strI = strI.substring("cloneId = [ ".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
clonePanelId = strI;
} else if(strI.startsWith("sheet = [")){
strI = strI.substring("sheet = [ ".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
sheet = strI;
}
LinkedList oInputs = node.getOtherOpInput();
for(POtherOpInput oInput : oInputs) {
strI = oInput.toString();
if(strI.startsWith("panel = [")) {
strI = strI.substring("panel = [ ".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
panelId = strI;
} else if(oInput.toString().startsWith(", cloneId = [")) {
strI = strI.substring(", cloneId = [".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
clonePanelId = strI;
} else if(oInput.toString().startsWith(", sheet = [")) {
strI = strI.substring(", sheet = [".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
sheet = strI;
}
}
} else {
clonePanelId = closePanelInput.toString().trim();
}
clonePanelId = trimQuotes(clonePanelId);
addPanelForCurrentIndex(clonePanelId);
// need to add for all the current layers
// in the original panel
Map> currentLayers = this.layerMap.get(panelId);
if(currentLayers != null && !currentLayers.isEmpty()) {
LAYER_LOOP : for(String layerId : currentLayers.keySet()) {
// grab the last index
// and see if we are removing that layer
List indices = currentLayers.get(layerId);
int lastIndex = indices.get(indices.size()-1);
// do we have a removal on this panel and this layer
if(this.lastRemovePanelLayerMap.containsKey(panelId)) {
Map lastLayerRemove = this.lastRemovePanelLayerMap.get(panelId);
if(lastLayerRemove.containsKey(layerId)) {
// need to compare this index
// to the removal
if(lastLayerRemove.get(layerId) > lastIndex) {
continue LAYER_LOOP;
}
}
}
// past the above logic
// so we can proceed
addLayerForCurrentIndex(clonePanelId, layerId);
}
}
// store the order of the creation
panelCreationOrder.add(clonePanelId);
// in the case when you cloned but the original panel has been modified
// we dont want to clone the new modification
// but the original
// so we need to keep track of the original of the clone in case it is used
// first, find the index of the current panel we are cloning from
// this is why we keep track of the curPanelId
panelId = trimQuotes(panelId);
Integer lastIndex = getLastPixelTaskIndexForPanel(panelId);
this.cloneToOrigTask.put(clonePanelId, lastIndex);
this.clonePanelToOrigPanel.put(clonePanelId, panelId);
// store the index of the clone to the panel created
this.cloneIndexToClonePanelId.put(index, clonePanelId);
this.cloneIdToIndex.put(clonePanelId, index);
// also store the sheet
if(sheet != null) {
sheet = trimQuotes(sheet);
if(!sheetList.contains(sheet)) {
sheetList.add(sheet);
}
}
}
else if (reactorId.equals("SetPanelView")) {
// here, if we did a clone
// but later changed the panel view
// i want to no longer keep the clone as part of the optimized recipe
String view = node.getOpInput().toString().trim();
if(view.startsWith("\"")) {
view = view.substring(1);
}
if(view.endsWith("\"")) {
view = view.substring(0, view.length()-1);
}
addPanelView(this.curPanelId, view);
}
// account for order of panel creation
else if(reactorId.equals("AddPanel")) {
// store order of panel creation
String panel = null;
String sheet = null;
POpInput input = node.getOpInput();
if(input instanceof ANounOpInput) {
// see if this starts with panel = [
String strI = input.toString();
if(strI.startsWith("panel = [")) {
strI = strI.substring("panel = [ ".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
panel = strI;
} else if(strI.startsWith("sheet = [")){
strI = strI.substring("sheet = [ ".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
sheet = strI;
}
LinkedList oInputs = node.getOtherOpInput();
for(POtherOpInput oInput : oInputs) {
strI = oInput.toString();
if(oInput.toString().startsWith(", panel = [")) {
strI = strI.substring(", panel = [".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
panel = strI;
} else if(oInput.toString().startsWith(", sheet = [")) {
strI = strI.substring(", sheet = [".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
sheet = strI;
}
}
} else {
panel = input.toString().trim();
}
panel = trimQuotes(panel);
panelCreationOrder.add(panel);
// also store the sheet
if(sheet != null) {
sheet = trimQuotes(sheet);
if(!sheetList.contains(sheet)) {
sheetList.add(sheet);
}
}
}
// account for new panel creation
else if(reactorId.equals("AddPanelIfAbsent")) {
// store order of panel creation
POpInput input = node.getOpInput();
String panel = input.toString().trim();
panel = trimQuotes(panel);
if(!panelCreationOrder.contains(panel)) {
panelCreationOrder.add(panel);
}
}
// remove the layer
else if(reactorId.equals("RemoveLayer")) {
this.removeLayerIndices.add(this.index);
// we also need to store the panel -> layer -> removal
POpInput input = node.getOpInput();
String panel = null;
String layer = null;
if(input instanceof ANounOpInput) {
// see if this starts with panel = [
String strI = input.toString();
if(strI.startsWith("panel = [")) {
strI = strI.substring("panel = [ ".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
panel = strI;
} else if(strI.startsWith("layer = [")){
strI = strI.substring("layer = [ ".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
layer = strI;
}
LinkedList oInputs = node.getOtherOpInput();
for(POtherOpInput oInput : oInputs) {
strI = oInput.toString();
if(oInput.toString().startsWith(", panel = [")) {
strI = strI.substring(", panel = [".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
panel = strI;
} else if(oInput.toString().startsWith(", layer = [")) {
strI = strI.substring(", layer = [".length()).trim();
strI = strI.substring(0, strI.length()-1).trim();
layer = strI;
}
}
panel = trimQuotes(panel);
layer = trimQuotes(layer);
Map lastLayerMap = null;
if(this.lastRemovePanelLayerMap.containsKey(panel)) {
lastLayerMap = this.lastRemovePanelLayerMap.get(panel);
} else {
lastLayerMap = new HashMap<>();
this.lastRemovePanelLayerMap.put(panel, lastLayerMap);
}
lastLayerMap.put(layer, this.index);
}
}
// need to account for auto tasks
// need to account for algorithms that just send data to the FE directly
else if(reactorId.equals("AutoTaskOptions") || taskReactors.contains(reactorId) ) {
// this is a constant task
// let the inAGeneric and inAWordOrIdScalar handle getting the correct panel id
containsTaskOptions = true;
}
// need to account for task ornaments
else if(taskOrnamentReactors.contains(reactorId)) {
// this is a panel ornament task
// need to account for this differently
// you can technically passin the panel directly
// so will first see if a panel has been defined or not
if(this.curPanelId != null) {
addPanelOrnamentTaskForCurrentIndex(this.curPanelId);
} else {
containsOrnamentTaskOptions = true;
}
}
// add a sheet
else if(reactorId.equals("AddSheet")) {
POpInput input = node.getOpInput();
String sheet = input.toString().trim();
sheet = trimQuotes(sheet);
sheetList.add(sheet);
}
// removing a sheet
else if(reactorId.equals("CloseSheet")) {
POpInput input = node.getOpInput();
String sheet = input.toString().trim();
sheet = trimQuotes(sheet);
sheetList.remove(sheet);
}
// is this the config layout
else if(reactorId.equals("SetInsightGoldenLayout")) {
captureMap = true;
SetInsightGoldenLayoutReactor gLayout = new SetInsightGoldenLayoutReactor();
initMapReactor(gLayout);
}
// is this the config layout
else if(reactorId.equals("SetInsightConfig")) {
captureMap = true;
SetInsightGoldenLayoutReactor iConfig = new SetInsightGoldenLayoutReactor();
initMapReactor(iConfig);
}
}
@Override
public void outAOperation(AOperation node) {
String reactorId = node.getId().toString().trim();
if(reactorId.equals("SetInsightConfig")) {
NounMetadata configMap = deInitMapReactor();
this.insightConfig = (Map) configMap.getValue();
captureMap = false;
}
}
@Override
public void inANoun(ANoun node) {
String key = node.getId().toString().trim();
if(key.equals(ReactorKeysEnum.PANEL.getKey())) {
containsPanelKey = true;
}
}
@Override
public void outANoun(ANoun node) {
// reset
containsPanelKey = false;
}
@Override
public void inAScalarRegTerm(AScalarRegTerm node) {
if(containsTaskOptions && containsPanelKey) {
// this is the value for a panel
// store it with the current index
String panel = node.toString().trim();
if(panel.startsWith("\"") || panel.startsWith("'")) {
panel = panel.substring(1);
}
if(panel.endsWith("\"") || panel.endsWith("'")) {
panel = panel.substring(0, panel.length()-1);
}
addPanelForCurrentIndex(panel);
// add for layer
// should technically drop all the other layers for these
addLayerForCurrentIndex(panel, "0");
} else if(containsOrnamentTaskOptions && containsPanelKey) {
// this is the value for a panel
// store it with the current index
String panel = node.toString().trim();
if(panel.startsWith("\"") || panel.startsWith("'")) {
panel = panel.substring(1);
}
if(panel.endsWith("\"") || panel.endsWith("'")) {
panel = panel.substring(0, panel.length()-1);
}
addPanelOrnamentTaskForCurrentIndex(panel);
}
}
/**
* Add the panel and the current index
* If first time seeing panel, adds panel key
* If already seen panel, adds to the set of indices for this panel
* @param panel
*/
private void addPanelForCurrentIndex(String panel) {
panel = panel.trim();
if (panelMap.keySet().contains(panel)) {
// if the panel DOES already exist in the panelMap, we just need to add the expression id to the set of values
// first get the existing set of index values
List indexVals = panelMap.get(panel);
// next, add the new index value to the list of values
if(!indexVals.contains(index)) {
indexVals.add(index);
}
} else {
// if the panel DOES NOT already exist in the panelMap, we need to add it
List indexVals = new ArrayList();
indexVals.add(index);
panelMap.put(panel, indexVals);
}
}
/**
* Add the panel and the current index
* If first time seeing panel, adds panel key + layer key
* If already seen panel, adds to the set of indices for this panel
* @param panel
*/
private void addLayerForCurrentIndex(String panel, String layer) {
panel = panel.trim();
layer = layer.trim();
if (layerMap.keySet().contains(panel)) {
List layerIndex = null;
// if it does exist
// is this the first layer
// or a new layer?
Map> layerIdsMap = layerMap.get(panel);
// next, add the new index value to the list of values
if(layerIdsMap.containsKey(layer)) {
layerIndex = layerIdsMap.get(layer);
} else {
layerIndex = new Vector();
layerIdsMap.put(layer, layerIndex);
}
if(!layerIndex.contains(index)) {
layerIndex.add(index);
}
} else {
// panel doesn't exist at all
List layerIndex = new Vector();
Map> layerIdsMap = new HashMap>();
layerIdsMap.put(layer, layerIndex);
layerIndex.add(index);
layerMap.put(panel, layerIdsMap);
}
}
/**
* Same as addPanelForCurrentIndex
* But for task ornaments
* @param panel
*/
private void addPanelOrnamentTaskForCurrentIndex(String panel) {
panel = panel.trim();
if (panelOrnamentMap.keySet().contains(panel)) {
// if the panel DOES already exist in the panelMap, we just need to add the expression id to the set of values
// first get the existing set of index values
List indexVals = panelOrnamentMap.get(panel);
// next, add the new index value to the list of values
if(!indexVals.contains(index)) {
indexVals.add(index);
}
} else {
// if the panel DOES NOT already exist in the panelMap, we need to add it
List indexVals = new ArrayList();
indexVals.add(index);
panelOrnamentMap.put(panel, indexVals);
}
}
private void addPanelView(String panel, String view) {
panel = panel.trim();
if (this.panelToPanelView.keySet().contains(panel)) {
// if the panel DOES already exist in the panelToPanelView, we just need to add the new expression
// of index to view
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy