
prerna.reactor.PowAssimilator Maven / Gradle / Ivy
The newest version!
package prerna.reactor;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codehaus.plexus.util.StringUtils;
import prerna.sablecc2.om.PixelDataType;
import prerna.sablecc2.om.nounmeta.NounMetadata;
import prerna.sablecc2.om.task.TaskUtility;
import prerna.util.Constants;
public class PowAssimilator extends Assimilator {
private static final Logger LOGGER = LogManager.getLogger(PowAssimilator.class.getName());
private String lSignature;
private String rSignature;
@Override
public NounMetadata execute() {
modifyForEmbeddedScripts();
modifySignatureFromLambdas();
// in order to ensure that we are properly creating the object as a double
// we need to remove any wrapping parenthesis such that we can
// properly make it a double by multiplying by 1.0
for(String formula : formulas) {
this.lSignature = StringUtils.replaceOnce( this.lSignature, formula, "( 1.0 * " + formula.substring(1, formula.length()));
this.rSignature = StringUtils.replaceOnce( this.rSignature, formula, "( 1.0 * " + formula.substring(1, formula.length()));
}
// while(lSignature.startsWith("(") && lSignature.endsWith(")")) {
// lSignature = lSignature.substring(1, lSignature.length()-1).trim();
// }
// while(rSignature.startsWith("(") && rSignature.endsWith(")")) {
// rSignature = rSignature.substring(1, rSignature.length()-1).trim();
// }
// evaluate the assimilator as an object
ClassMaker maker = new ClassMaker();
// keep a string to generate the method to execute that will
// return an object that runs the expression
StringBuilder expressionBuilder = new StringBuilder();
expressionBuilder.append("public Object getExpressionValue(){");
// we need to grab any variables and define them at the top of the method
appendVariables(expressionBuilder);
// now that the variables are defined
// we just want to add the expression as a return
expressionBuilder.append("return new java.math.BigDecimal(Math.pow( 1.0 * " + lSignature + ", 1.0 * " + rSignature + "));}");
maker.addMethod(expressionBuilder.toString());
// add a super so we have a base method to execute
maker.addSuper(AssimilatorEvaluator.class.getName());
Class newClass = maker.toClass();
// noun object to return
// need to cast to get the type of the NounMetadata object
NounMetadata noun = null;
try {
AssimilatorEvaluator newInstance = (AssimilatorEvaluator) newClass.newInstance();
noun = newInstance.execute();
// to avoid java error which cannot be caught
// if the return is null
// we will throw the exception here
// which means we could not evaluate the signature
if(noun == null) {
throw new IllegalArgumentException("Error!!! Could not properly evaluate expression = " + this.signature);
}
} catch (InstantiationException | IllegalAccessException e) {
LOGGER.error(Constants.STACKTRACE, e);
}
return noun;
}
@Override
public void modifySignature(String stringToFind, String stringReplacement) {
// for this special reactor
// we need to run this on both the
// left hand side and
// right hand size
LOGGER.debug("Original left signature value = " + this.lSignature);
this.lSignature = StringUtils.replaceOnce( this.lSignature, stringToFind, stringReplacement);
LOGGER.debug("New left signature value = " + this.lSignature);
LOGGER.debug("Original right signature value = " + this.rSignature);
this.rSignature = StringUtils.replaceOnce( this.rSignature, stringToFind, stringReplacement);
LOGGER.debug("New right signature value = " + this.rSignature);
}
/**
* Modify the expression for embedded scripts
*/
@Override
protected void modifyForEmbeddedScripts() {
// need to account for embedded scripts that we want to evaluate
List lambdas = curRow.getNounsOfType(PixelDataType.LAMBDA);
for(int i = 0; i < lambdas.size(); i++) {
NounMetadata n = lambdas.get(i);
if(n.getValue() instanceof EmbeddedScriptReactor) {
// replace the value with the output
NounMetadata output = ((EmbeddedScriptReactor) n.getValue()).execute();
PixelDataType dataType = output.getNounType();
if(dataType == PixelDataType.CONST_DECIMAL || dataType == PixelDataType.CONST_INT) {
this.lSignature = StringUtils.replaceOnce( this.lSignature, ((EmbeddedScriptReactor) n.getValue()).getOriginalSignature(), output.getValue().toString());
this.rSignature = StringUtils.replaceOnce( this.rSignature, ((EmbeddedScriptReactor) n.getValue()).getOriginalSignature(), output.getValue().toString());
} else if(dataType == PixelDataType.FORMATTED_DATA_SET || dataType == PixelDataType.TASK) {
NounMetadata formatData = TaskUtility.getTaskDataScalarElement(output);
if(formatData == null) {
throw new IllegalArgumentException("Can only handle query data that is a scalar input");
} else {
Object newValue = formatData.getValue();
PixelDataType newDataType = formatData.getNounType();
if(newDataType == PixelDataType.CONST_DECIMAL || newDataType == PixelDataType.CONST_INT) {
this.lSignature = StringUtils.replaceOnce( this.lSignature, ((EmbeddedScriptReactor) n.getValue()).getOriginalSignature(), newValue.toString());
this.rSignature = StringUtils.replaceOnce( this.rSignature, ((EmbeddedScriptReactor) n.getValue()).getOriginalSignature(), newValue.toString());
}
}
} else {
throw new IllegalArgumentException("Unable to handle this type of input");
}
}
}
}
/**
* Append the variables used within the expression
* @param expressionBuilder
*/
private void appendVariables(StringBuilder expressionBuilder) {
List inputColumns = curRow.getAllColumns();
// these input columns should be defined at the beginning of the expression
// technically, someone can use the same variable multiple times
// so need to account for this
// ... just add them to a set and call it a day
Set uniqueInputs = new HashSet();
uniqueInputs.addAll(inputColumns);
for(String input : uniqueInputs) {
NounMetadata data = planner.getVariableValue(input);
if(data == null) {
// this only happens when a variable is being used but isn't defined
throw new IllegalArgumentException("Undefined variable : " + input);
}
PixelDataType dataType = data.getNounType();
// we have a double that is stored
if(dataType == PixelDataType.CONST_DECIMAL) {
expressionBuilder.append("double ").append(input).append(" = ").append(data.getValue()).append(";");
}
// we have an integer that is stored
else if(dataType == PixelDataType.CONST_INT) {
expressionBuilder.append("int ").append(input).append(" = ").append(data.getValue()).append(";");
}
// we have a lambda
// so we execute and return the operation output
// TODO: this should no longer be needed since getVariableValue will evaluate a lambda
else if(dataType == PixelDataType.LAMBDA){
// in case the variable points to another reactor
// that we need to get the value from
// evaluate the lambda
// object better be a reactor to run
Object rVal = data.getValue();
if(rVal instanceof IReactor) {
NounMetadata newNoun = ((IReactor) rVal).execute();
PixelDataType newDataType = data.getNounType();
if(newDataType == PixelDataType.CONST_DECIMAL) {
expressionBuilder.append("double ").append(input).append(" = ").append(newNoun.getValue()).append(";");
} else if(newDataType == PixelDataType.CONST_INT) {
expressionBuilder.append("int ").append(input).append(" = ").append(newNoun.getValue()).append(";");
}
} else {
// this should never ever happen....
throw new IllegalArgumentException("Assimilator cannot handle this type if input");
}
} else {
throw new IllegalArgumentException("Assimilator can currently only handle outputs of scalar variables");
}
}
}
public void setExpressions(String lSignature, String rSignature) {
this.lSignature = lSignature;
this.rSignature = rSignature;
}
@Override
public List getOutputs() {
List outputs = super.getOutputs();
if(outputs != null) {
return outputs;
}
outputs = new Vector();
NounMetadata output = new NounMetadata(this.signature, PixelDataType.LAMBDA);
outputs.add(output);
return outputs;
}
@Override
public String getJavaSignature() {
// replace all the values that is inside this. this could be a recursive call
for(int i = 0; i < curRow.size(); i++) {
NounMetadata thisLambdaMeta = curRow.getNoun(i);
Object nextValue = (Object)thisLambdaMeta.getValue();
String strToFind = null;
String replaceValue = null;
if(nextValue instanceof JavaExecutable && nextValue instanceof IReactor) {
replaceValue = ((JavaExecutable)nextValue).getJavaSignature();
strToFind = ((IReactor)nextValue).getOriginalSignature();
} else {
continue;
}
modifySignature(strToFind, replaceValue);
}
return "new Double(Math.pow( 1.0 * " + lSignature + ", 1.0 * " + rSignature + "));";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy