
prerna.reactor.json.GreedyJsonReactor Maven / Gradle / Ivy
The newest version!
package prerna.reactor.json;
import java.lang.reflect.Modifier;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.validator.routines.DateValidator;
import org.apache.commons.validator.routines.DoubleValidator;
import org.apache.commons.validator.routines.EmailValidator;
import org.apache.commons.validator.routines.IntegerValidator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import prerna.reactor.AbstractReactor;
import prerna.reactor.IReactor;
import prerna.sablecc2.om.GenRowStruct;
import prerna.sablecc2.om.NounStore;
import prerna.sablecc2.om.PixelDataType;
import prerna.sablecc2.om.nounmeta.NounMetadata;
import prerna.util.Constants;
public class GreedyJsonReactor extends AbstractReactor {
private static final Logger logger = LogManager.getLogger(GreedyJsonReactor.class);
public static final String ERROR = "ERROR";
public static final String STAGE = "STAGE";
public static final String CHILDS = "CHILDS";
public static final String DATA = "DATA";
public static final String FULL_MESSAGE = "FULL_MESSAGE";
public static final String SQL = "SQL";
public static final String TXN = "TXN";
// gets the top most parent
// just an optimization so I dont need to go about finding this information
IReactor superParent = null;
boolean error = false;
public Hashtable inputHash = new Hashtable();
public Hashtable outputHash = new Hashtable();
public Hashtable errorHash = new Hashtable();
public List keysToValidate = new Vector<>();
// set which fields you think are in what bucket
// these fields should not be null
protected String [] mandatoryFields = {};
// these fields should be dates
protected String [] dateFields = {};
// these are email fields
protected String [] emailFields = {};
// these are number fields
protected String [] intFields = {};
// these are zipcode Fields
protected String [] zipFields = {};
// these are npi fields
protected String [] npiFields = {};
// these are npi fields
protected String [] ssnFields = {};
// these are npi fields
protected String [] phoneFields = {};
// Need a way to keep the output structure
// may be I keep doing an add level ?
// everytime I see a new mapentry which is not a new reactor or even if it is
// I add a new hashtable with that entry and record it there as part of curnoun call
// which basically means, I also need some way to say set this value somewhere in that hierarchy
// question is what happens if I have 2 "different" values set up at different levels
// The only way to resolve this problem is introduce an intermediary reactor which will set the specific value
// which I think is not a bad idea
// I also need a way to look up stuff i.e. get this to me in parent or child type stuff
// getFromParent("keyname", boolean levels) / getFromChild("keyname", boolean levels)
// when I set the value of the result
// I will always set this in the child
// the typical the execute will be the validate
// and the out will be where you either get the results back or you get the errors back
// the only problem is out has to directly synchronize with parent nounsttore
// the only issue is there is another child with the same name
// how do we account
// wait I dont need to because it will be an array and will continue to be.. ok
// need to test this possibility
// When there is an error, the error will have a key which says ERROR to be tracked
// the error can be true / false
// when error is true
// the errors are tracked at an element level
// the errors are kept as one of the keys on hashtable
// the actual error to display will be recorded through
// the - __ERROR and value - this is the one to be displayed if we so chose
// when error is false
// the element level gives you the actual value
// either we can stop on the first error or
// run through everything.. assimilate the error and give back
// when the parent is empty, we do the childs recursion to get to it
// and clean up childs ?
@Override
public NounMetadata execute() {
process();
Hashtable daOutput = getOutput();
return new NounMetadata(daOutput, PixelDataType.MAP);
}
// This method will be overridden in the case of processor
// this will execute the sql and then jam the result back in
public Hashtable getOutput()
{
// need to get all the nouns but the noun all and then send it out from there
if(!store.getNoun(NounStore.all).isEmpty())
{
// move it to something else
GenRowStruct rowStruct = this.store.getNoun(NounStore.all);
// set it as something else
if(reactorName == null || reactorName.isEmpty())
reactorName = DATA;
this.store.addNoun(reactorName, rowStruct);
}
this.store.nounRow.remove(NounStore.all);
// I need to run row by row and turn it into a full data object
// I created a method in nounstore for this
// this is now in the store
// also add the childs here
if(hasProp(CHILDS))
{
// need to add the noun to nounstore as well
NounMetadata nmd = new NounMetadata(getProp(CHILDS), PixelDataType.MAP);
GenRowStruct grs = new GenRowStruct();
grs.add(nmd);
this.store.addNoun(CHILDS, grs);
}
// if there are errors plug the errors also ?
if(errorHash.size() > 0)
{
NounMetadata nmd = new NounMetadata(errorHash, PixelDataType.MAP);
GenRowStruct grs = new GenRowStruct();
grs.add(nmd);
this.store.addNoun(ERROR, grs);
}
// need a way to say this is an array
// so push everything to array and if so process as array
return this.store.getDataHash();
}
@Override
public Object Out() {
// do the database stuff
// synchronize everything with the parent
// if it got to this point there was no error so we are good at this point
// see if someone has plugged in errors
return this.parentReactor;
}
public void process()
{
// this will be overridden to validate or process
}
public void addError(String element, String errorDescription)
{
// need to add the elements appropriately here
errorHash.put(element+ "__"+ ERROR, errorDescription);
outputHash.put(element, ERROR);
Vector
errorVector = null;
if(outputHash.containsKey(ERROR))
errorVector = (Vector)outputHash.get(ERROR);
else
errorVector = new Vector<>();
errorVector.add(element);
errorHash.put(ERROR + "_ELEMENTS", errorVector);
outputHash.put(ERROR, errorVector);
}
public void addErrorWithStage(String element, String errorDescription, String stage)
{
addError(element, errorDescription);
errorHash.put(element+ "__" + STAGE, stage);
}
// this is the recursive piece
public boolean isError()
{
boolean retError = false;
Vector dataHashVector = new Vector<>();
// we can optimize the creation of dataHash but..
dataHashVector.add(this.store.getDataHash());
return hasError(dataHashVector);
}
// this is doing breadth first.. we could change it to depth first if we so chose to
public boolean hasError(Vector remainingHash)
{
// all the childs are in the childs key
// if(hasError)
// return hasError;
Vector nextLevelHash = new Vector<>();
// If I reach until end or if there is an error in between
for(int nodeIndex = 0; nodeIndex < remainingHash.size();nodeIndex++)
{
Hashtable childHash = (Hashtable)remainingHash.get(0);
// if noError is true and childHash doesn't contain error
error = error || (childHash.containsKey(ERROR));
// now get all the childs from this one and add it to the next level
if(childHash.containsKey(CHILDS))
{
Vector childs = (Vector)childHash.get(CHILDS);
for(int childIndex = 0;childIndex < childs.size();childIndex++) {
if(childHash.get(childs.get(childIndex)) instanceof Hashtable) {
nextLevelHash.add((Hashtable)childHash.get(childs.get(childIndex)));
}
}
}
}
// no more to go.. yay !!
if(!nextLevelHash.isEmpty() && !error)
hasError(nextLevelHash);
return error;
}
public Hashtable getCleanOutput()
{
boolean hasError = isError();
Hashtable mainTable = new Hashtable();
if(hasError)
{
mainTable = store.getDataHash();
Vector allHashes = new Vector<>();
allHashes.add(mainTable);
while(!allHashes.isEmpty())
{
Hashtable thisHash = allHashes.remove(0);
if(thisHash.containsKey(CHILDS))
{
Vector childs = (Vector)thisHash.get(CHILDS);
for(int childIndex = 0;childIndex < childs.size();childIndex++)
{
// seems to come 2 times need to see why
if(thisHash.containsKey(childs.get(childIndex)))
{
// need to make a check to see if this is an array
// if so leave it
if(thisHash.get(childs.get(childIndex)) instanceof Hashtable)
allHashes.add((Hashtable)thisHash.get(childs.get(childIndex)));
else
logger.debug("Find out what this is is then ?!");
//thisHash.remove(childs.get(childIndex));
}
}
thisHash.remove(CHILDS);
}
thisHash.remove("all");
}
}
mainTable.put("IS_ERROR", hasError);
return mainTable;
}
// the idea here is to take the sql thaat is there
// print it out
// in the right location
public Hashtable getFullOutput()
{
boolean hasError = isError();
Hashtable mainTable = new Hashtable();
if(hasError)
{
mainTable = store.getDataHash();
Vector allHashes = new Vector<>();
allHashes.add(mainTable);
while(!allHashes.isEmpty())
{
Hashtable thisHash = allHashes.remove(0);
if(thisHash.containsKey(CHILDS))
{
Vector childs = (Vector)thisHash.get(CHILDS);
for(int childIndex = 0;childIndex < childs.size();childIndex++)
{
// seems to come 2 times need to see why
if(thisHash.containsKey(childs.get(childIndex)))
{
// need to make a check to see if this is an array
// if so leave it
if(thisHash.get(childs.get(childIndex)) instanceof Hashtable)
allHashes.add((Hashtable)thisHash.get(childs.get(childIndex)));
else
logger.debug("Find out what this is is then ?!");
}
}
thisHash.remove(CHILDS);
}
thisHash.remove("all");
}
}
mainTable.put("IS_ERROR", hasError);
return mainTable;
}
public StringBuffer getJsonOutput()
{
StringBuffer retOutput = new StringBuffer();
// right now I am keeping everything
Gson gson = new GsonBuilder()
.disableHtmlEscaping()
.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT)
//.registerTypeAdapter(Double.class, new NumberAdaptor())
.create();
String propString = gson.toJson(this.store.getDataHash());
retOutput.append(propString);
/*
retOutput.append("{");
Vector nextLevelHash = new Vector();
// I need to do a couple of things here
// get the data hash
// remove the childs, all
// add the childs to the next vector
// print the key and the value
for(int nodeIndex = 0;nodeIndex < childVector.size();nodeIndex++)
{
Hashtable childHash = childVector.get(nodeIndex);
childHash.remove("all");
if(childHash.containsKey(CHILDS))
{
Vector childs = (Vector)childHash.get(CHILDS);
for(int childIndex = 0;childIndex < childs.size();childIndex++)
{
nextLevelHash.add((Hashtable)childHash.get(childs.get(childIndex)));
childHash.remove(childs.get(childIndex));
}
}
// now that I have the pure hashtable print it out
Gson gson = new GsonBuilder()
.disableHtmlEscaping()
.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT)
//.registerTypeAdapter(Double.class, new NumberAdaptor())
.create();
String propString = gson.toJson(childHash);
// send this for output again
retOutput.append(propString);
}
retOutput.append("}");
*/
return retOutput;
}
public List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy