All Downloads are FREE. Search and download functionalities are using the official Maven repository.

prerna.query.querystruct.evaluator.QueryStructExpressionIterator Maven / Gradle / Ivy

The newest version!
package prerna.query.querystruct.evaluator;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import prerna.algorithm.api.SemossDataType;
import prerna.engine.api.IHeadersDataRow;
import prerna.engine.api.IRawSelectWrapper;
import prerna.om.HeadersDataRow;
import prerna.query.querystruct.SelectQueryStruct;
import prerna.query.querystruct.selectors.IQuerySelector;
import prerna.query.querystruct.selectors.QueryFunctionSelector;
import prerna.rdf.engine.wrappers.AbstractWrapper;

public class QueryStructExpressionIterator extends AbstractWrapper implements IRawSelectWrapper {

	/**
	 * It is really difficult to figure out the traversals in order to perform multiple math routines
	 * on columns... granted, I am dumb, so if you can figure it out, please fix the GremlinInterpreter class
	 * 
	 * So if there is math or something else that needs to be done, we are doing it programmatically through Java
	 */
	
	private static final Logger classLogger = LogManager.getLogger(QueryStructExpressionIterator.class.getName());
	
	private List processedData;
	private int processedDataSize;
	private int processedDataPosition;

	private IRawSelectWrapper subIt;
	private SelectQueryStruct qs;

	public QueryStructExpressionIterator(IRawSelectWrapper subIt, SelectQueryStruct qs) {
		this.subIt = subIt;
		this.qs = qs;
	}

	@Override
	public void execute() {
		// first, see that there is math that is needed
		List selectors = this.qs.getSelectors();
		int numSelectors = selectors.size();

		List uniqueSelectorNames = new ArrayList(numSelectors);
		List mathIndex = new ArrayList(numSelectors);
		List mathOperation = new ArrayList(numSelectors);
		List groupByIndex = new ArrayList(numSelectors);
		String[] headers = new String[numSelectors];

		for(int i = 0; i < numSelectors; i++) {
			IQuerySelector selector = selectors.get(i);
			if(selector.getSelectorType() == IQuerySelector.SELECTOR_TYPE.FUNCTION) {
				QueryFunctionSelector mSelector = (QueryFunctionSelector) selector;
				mathIndex.add(i);
				mathOperation.add(mSelector.getFunction());
			}
			uniqueSelectorNames.add(selector.getQueryStructName());
			headers[i] = selector.getAlias();
		}

		List groups = this.qs.getGroupBy();
		int numGroups = groups.size();
		for(int i = 0; i < numGroups; i++) {
			IQuerySelector gSelector = groups.get(i);
		    groupByIndex.add(uniqueSelectorNames.indexOf(gSelector.getQueryStructName()));
		}

		if(!mathIndex.isEmpty()) {
			// we need to process through this iterator to get our results
			calculateProcessedData(headers, uniqueSelectorNames, mathIndex, mathOperation, groupByIndex);
			this.rawHeaders = headers;
			this.headers = headers;
			this.numColumns = headers.length;
			this.types = new SemossDataType[this.numColumns];
			SemossDataType[] origTypes = this.subIt.getTypes();
			for(int i = 0; i < this.numColumns; i++) {
				if(groupByIndex.contains(new Integer(i))) {
					this.types[i] = SemossDataType.DOUBLE;
				} else {
					this.types[i] = origTypes[i];
				}
			}
		}
	}
	
	private void calculateProcessedData(String[] retHeaders,
			List uniqueSelectorNames, 
			List mathIndex, 
			List mathOperation, 
			List groupByIndex) {
		this.processedData = new Vector();
		int numSelectors = uniqueSelectorNames.size();
		int numMathIndex = mathIndex.size();
		int numGroups = groupByIndex.size();

		// need to use a map so i can group things
		Map> store = new LinkedHashMap>();
		while(subIt.hasNext()) {
			Object[] dataRow = subIt.next().getValues();
			String gStr = groupByStr(dataRow, numGroups, groupByIndex);
			
			List valuesStore = null;
			if(store.containsKey(gStr)) {
				valuesStore = store.get(gStr);
			} else {
				valuesStore = new ArrayList();
				for(int i = 0; i < numMathIndex; i++) {
					valuesStore.add(IQueryStructExpression.getExpression(mathOperation.get(i)));
				}
				store.put(gStr, valuesStore);
			}
			
			for(int counter = 0; counter < numMathIndex; counter++) {
				Integer mathColIdx = mathIndex.get(counter);
				valuesStore.get(counter).processData(dataRow[mathColIdx]);
			}
		}
		
		// now i need to flatten this and preserve the headers
		for(String groupByStr : store.keySet()) {
			// add the group by indices
			Object[] row = new Object[numSelectors];
			if(numGroups == 1) {
				row[groupByIndex.get(0)] = groupByStr;
			} else {
				String[] split = groupByStr.split("\\+\\+\\+");
				for(int i = 0; i < numGroups; i++) {
					row[groupByIndex.get(i)] = split[i];
				}
			}
			
			List calculations = store.get(groupByStr);
			// add the columns which had derivations
			for(int i = 0; i < numMathIndex; i++) {
				row[mathIndex.get(i)] = calculations.get(i).getOutput();
			}
			
			// add to processed data
			this.processedData.add(new HeadersDataRow(retHeaders, row));
		}
		this.processedDataSize = this.processedData.size();
	}
	
	private String groupByStr(Object[] dataRow, int numGroups, List groupByIndex) {
		StringBuilder gStr = new StringBuilder();
		for(int i = 0; i < numGroups; i++) {
			int index = groupByIndex.get(i);
			if(i == 0) {
				gStr.append(dataRow[index]);
			} else {
				gStr.append("+++").append(dataRow[index]);

			}
		}
		return gStr.toString();
	}

	@Override
	public boolean hasNext() {
		if(processedData == null) {
			return this.subIt.hasNext();
		} else {
			if(processedDataPosition + 1 > processedDataSize) {
				return false;
			}
			return true;
		}
	}

	@Override
	public IHeadersDataRow next() {
		if(processedData == null) {
			return this.subIt.next();
		} else {
			IHeadersDataRow nextRow = processedData.get(processedDataPosition);
			processedDataPosition++;
			return nextRow;
		}
	}

	@Override
	public long getNumRows() throws Exception {
		if(this.numRows == 0) {
			if(processedData == null) {
				this.numRows = this.subIt.getNumRows();
			} else {
				this.numRows = processedDataSize;
			}
		}
		return this.numRows;
	}

	@Override
	public long getNumRecords() throws Exception {
		return getNumRows() * getHeaders().length;	
	}

	@Override
	public void close() throws IOException {
		this.subIt.close();
	}

	@Override
	public void reset() throws Exception {
		close();
		this.subIt.reset();
		execute();
	}

	@Override
	public String[] getHeaders() {
		if(this.headers == null) {
			return this.subIt.getHeaders();
		}
		return this.headers;
	}

	@Override
	public SemossDataType[] getTypes() {
		if(this.types == null) {
			return this.subIt.getTypes();
		}
		return this.types;
	}

	@Override
	public void setQuery(String query) {
		// this class doesn't set a query
		// it uses an existing datsource iterator
	}

	@Override
	public boolean flushable() {
		// TODO Auto-generated method stub
		return false;
	}
	
	@Override
	public String flush() {
		// TODO Auto-generated method stub
		return null;
	}
	
	///////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////

	/*
	 * Main for testing
	 */
	
//	public static void main(String[] args) throws Exception {
//		TestUtilityMethods.loadDIHelper("C:\\workspace\\Semoss_Dev\\RDF_Map.prop");
//		{
//			String engineProp = "C:\\workspace\\Semoss_Dev\\db\\LocalMasterDatabase.smss";
//			IEngine coreEngine = new RDBMSNativeEngine();
//			coreEngine.setEngineId("LocalMasterDatabase");
//			coreEngine.open(engineProp);
//			coreEngine.setEngineId("LocalMasterDatabase");
//			DIHelper.getInstance().setLocalProperty("LocalMasterDatabase", coreEngine);
//		}
//		
//	
//		String testEngine = "TinkerThis__cc2a91eb-548d-4970-91c3-7a043b783841";
//		String engineProp = "C:\\workspace\\Semoss_Dev\\db\\" + testEngine + ".smss";
//		TinkerEngine coreEngine = new TinkerEngine();
//		coreEngine.open(engineProp);
//		DIHelper.getInstance().setLocalProperty(testEngine, coreEngine);
//		
//		
//		GremlinInterpreter interp = new GremlinInterpreter(coreEngine.getGraph().traversal(), 
//				coreEngine.getTypeMap(), coreEngine.getNameMap());
//		
//		SelectQueryStruct qs = new SelectQueryStruct();
//		qs.addSelector(new QueryColumnSelector("Studio"));
//		QueryFunctionSelector fun = new QueryFunctionSelector();
//		fun.setFunction(QueryFunctionHelper.MEAN);
//		fun.addInnerSelector(new QueryColumnSelector("Title__MovieBudget"));
//		qs.addSelector(fun);
//		qs.addGroupBy(new QueryColumnSelector("Studio"));
//		qs.addRelation("Title", "Studio", "inner.join");
//		
//		RawGemlinSelectWrapper subIt = new RawGemlinSelectWrapper(interp, qs);
//		subIt.execute();
//		
//		QueryStructExpressionIterator it = new QueryStructExpressionIterator(subIt, qs);
//		it.execute();
//		while(it.hasNext()) {
//			System.out.println(it.next());
//		}
//	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy