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

com.scudata.expression.mfn.op.AttachGroup Maven / Gradle / Ivy

Go to download

SPL(Structured Process Language) A programming language specially for structured data computing.

There is a newer version: 20241126
Show newest version
package com.scudata.expression.mfn.op;

import java.util.ArrayList;

import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.Context;
import com.scudata.dm.op.Operable;
import com.scudata.expression.Expression;
import com.scudata.expression.Gather;
import com.scudata.expression.IParam;
import com.scudata.expression.Node;
import com.scudata.expression.OperableFunction;
import com.scudata.expression.ParamInfo2;
import com.scudata.expression.fn.algebra.Var;
import com.scudata.resources.EngineMessage;

/**
 * ???α??ܵ????????????????
 * op.group(x,??) op.group(x:F,??;y:G,??) op???α??ܵ?
 * @author RunQian
 *
 */
public class AttachGroup extends OperableFunction {
	public Object calculate(Context ctx) {
		if (param == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("group" + mm.getMessage("function.missingParam"));
		}

		if (option != null && option.indexOf('q') != -1) {
			if (param.getType() != IParam.Semicolon) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("group" + mm.getMessage("function.invalidParam"));
			}
			
			int size = param.getSubSize();
			if (size == 2) {
				IParam sub0 = param.getSub(0);
				IParam sub1 = param.getSub(1);
				if (sub0 == null || sub1 == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("group" + mm.getMessage("function.invalidParam"));
				}
				
				Expression []exps = sub0.toArray("group", false);
				Expression []sortExps = sub1.toArray("group", false);
				return operable.group(this, exps, sortExps, option, ctx);
			} else if (size == 3) {
				IParam sub0 = param.getSub(0);
				IParam sub1 = param.getSub(1);
				IParam sub2 = param.getSub(2);
				if (sub0 == null || sub1 == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("group" + mm.getMessage("function.invalidParam"));
				}

				ParamInfo2 pi0 = ParamInfo2.parse(sub0, "group", true, false);
				Expression []exps = pi0.getExpressions1();
				String []names = pi0.getExpressionStrs2();
				
				ParamInfo2 pi1 = ParamInfo2.parse(sub1, "group", true, false);
				Expression []sortExps = pi1.getExpressions1();
				String []sortNames = pi1.getExpressionStrs2();
				
				Expression []newExps = null;
				String []newNames = null;
				if (sub2 != null) {
					ParamInfo2 pi2 = ParamInfo2.parse(sub2, "group", true, false);
					newExps = pi2.getExpressions1();
					newNames = pi2.getExpressionStrs2();
				}
				
				return operable.group(this, exps, names, sortExps, sortNames, newExps, newNames, option, ctx);
			} else {
				MessageManager mm = EngineMessage.get();
				throw new RQException("group" + mm.getMessage("function.invalidParam"));
			}
		} else if (param.isLeaf()) {
			Expression exp = param.getLeafExpression();
			Expression []exps = new Expression[] {exp};
			return operable.group(this, exps, option, ctx);
		} else if (param.getType() == IParam.Comma) {
			if (option != null && option.indexOf('i') != -1) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("group" + mm.getMessage("function.invalidParam"));
			}
			
			int size = param.getSubSize();
			Expression []exps = new Expression[size];
			for (int i = 0; i < size; ++i) {
				IParam sub = param.getSub(i);
				if (sub == null || !sub.isLeaf()) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("group" + mm.getMessage("function.invalidParam"));
				}
				exps[i] = sub.getLeafExpression();
			}
			
			return operable.group(this, exps, option, ctx);
		} else if (param.getType() == IParam.Semicolon) {
			if (param.getSubSize() != 2) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("group" + mm.getMessage("function.invalidParam"));
			}
			
			IParam sub0 = param.getSub(0);
			if (sub0 == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("group" + mm.getMessage("function.invalidParam"));
			}

			ParamInfo2 pi0 = ParamInfo2.parse(sub0, "group", true, false);
			Expression []exps = pi0.getExpressions1();
			String []names = pi0.getExpressionStrs2();
			
			Expression []newExps = null;
			String []newNames = null;
			IParam sub1 = param.getSub(1);
			if (sub1 != null) {
				ParamInfo2 pi1 = ParamInfo2.parse(sub1, "group", true, false);
				newExps = pi1.getExpressions1();
				newNames = pi1.getExpressionStrs2();
			}
			
			if (option != null && option.indexOf('i') != -1 && exps.length != 1) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("group" + mm.getMessage("function.invalidParam"));
			}

			if (option != null && option.indexOf('s') != -1) {
				// ???????ʽ???Ⱥ;ۺϱ???ʽ????
				int elen = exps == null ? 0 : exps.length;
				int clen = newExps == null ? 0 : newExps.length;
				ArrayList gathers = new ArrayList(); // ͳ?ƾۺϺ???
				ArrayList poss = new ArrayList(); // ???????ʽ????Ӧ?ۺϺ????б??ĵڼ????ۺϺ???
				
				// ????????ʽ?еľۺϺ???
				for (int i = 0; i < clen; i++) {
					int size = gathers.size();
					gathers.addAll(Expression.getSpecFunc(newExps[i], Gather.class));
					
					if (size == gathers.size()) {
						Node home = newExps[i].getHome();
						if (home instanceof Var) {
							Var var = (Var)home;
							String param = var.getParamString();
							String opt = var.getOption();
							String sumStr = "sum(" + param + ")";
							Expression exp = new Expression(cs, ctx, sumStr);
							gathers.add(exp.getHome());
							
							String countStr = "count(" + param + ")";
							exp = new Expression(cs, ctx, countStr);
							gathers.add(exp.getHome());
							
							String sum2Str = "sum(power(" + param + "))";
							exp = new Expression(cs, ctx, sum2Str);
							gathers.add(exp.getHome());
							
							// sum2+count*power(sum/count) - 2*sum*sum/count
							String expStr = sum2Str + "+" + countStr + "*power(" + sumStr + "/" + countStr + 
									")-2*" + sumStr + "*" + sumStr + "/" + countStr;
							if (opt == null || opt.indexOf('s') == -1) {
								expStr = "(" + expStr + ")/" + countStr;
							} else {
								expStr = "(" + expStr + ")/(" + countStr + "-1)";
							}
							
							newExps[i] = new Expression(cs, ctx, expStr);
							if (newNames[i] == null || newNames[i].length() == 0) {
								newNames[i] = "var";
							}
						} else {
							gathers.add(newExps[i]);
						}
					}
					
					poss.add(gathers.size());
				}
				
				// ?????м?ۺϱ???ʽ
				Expression[] tempExps = new Expression[gathers.size()];
				for (int i = 0; i < tempExps.length; i++) {
					Object obj = gathers.get(i);
					if (obj instanceof Gather) {
						Gather gather = (Gather)gathers.get(i);
						tempExps[i] = new Expression(cs, ctx, gather.getFunctionString());
					} else {
						tempExps[i] = (Expression)gathers.get(i);
					}
				}
				
				// new ?α?ı???ʽ
				Expression[] senExps = new Expression[elen+clen];
				String strExp = null;	// ?ϱ???ʽ?ַ?????
				int index = 0;	// ?ϱ???ʽ??????
				
				// ?????ϱ???ʽ??ת??Ϊ?µ?new??ͳ???б???ʽ
				boolean exCal	= false;	// ?ж??Ƿ??־ۺϱ???ʽ
				if (newExps != null) {
					strExp = newExps[index].toString();
				}
				
				for (int i = 0; i < tempExps.length; i++) {
					if (i >= poss.get(index)) {
						senExps[index+elen] = new Expression(cs, ctx, strExp);
						index++;
						strExp = newExps[index].toString();
					}
					
					String funStr = "#" + (i+elen+1);
					strExp = Expression.replaceFunc(strExp, tempExps[i].toString(), funStr);
					if (!strExp.equals(funStr)) {
						exCal = true;
					}
				}
				
				String[] senNames	= null;	// ͳһ??????
				String[] tempNames	= newNames;	// ??ʱ??????
				if (exCal) {
					tempNames = null;	// ????Ҫ??new????????????ʱ??????Ϊ??
					// ??д???????ʽ
					for (int i = 1; i <= elen; i++) {
						String funStr = "#" + i;
						senExps[i-1] = new Expression(cs, ctx, funStr);
					}
					
					if (senExps.length > 0)	{// ???һ??????ʽ??????
						senExps[index+elen] = new Expression(cs, ctx, strExp);
					}
					
					// ????ͳһ??????
					senNames = new String[elen + newNames.length];
					for (int i = 0; i < elen; i++) {
						senNames[i] = names[i];
					}
					
					for (int i =  0; i < clen; i++) {
						if (null == newNames[i]) {
							senNames[i+elen] = newExps[i].toString();
						} else {
							senNames[i+elen] = newNames[i];
						}
					}
				}
				
				if (senNames == null) {
					return operable.group(this, exps, names, newExps, newNames, option, ctx);
				} else {
					Operable result = operable.group(this, exps, names, tempExps, tempNames, option, ctx);
					return result.newTable(null, senExps, senNames, null, ctx);
				}
			} else {
				return operable.group(this, exps, names, newExps, newNames, option, ctx);
			}
		} else {
			MessageManager mm = EngineMessage.get();
			throw new RQException("group" + mm.getMessage("function.invalidParam"));
		}
	}
}