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

com.scudata.expression.MemberFunction 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;

import com.scudata.array.BoolArray;
import com.scudata.array.IArray;
import com.scudata.array.ObjectArray;
import com.scudata.cellset.ICellSet;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.Context;
import com.scudata.dm.Current;
import com.scudata.dm.Sequence;
import com.scudata.resources.EngineMessage;
import com.scudata.util.Variant;

/**
 * ??Ա???????࣬??Ա??????ʵ??????Ҫ?̳??Դ???
 * @author WangXiaoJun
 *
 */
public abstract class MemberFunction extends Function {
	protected MemberFunction next; // ??һ??ͬ???ij?Ա??????
	protected Node left; // ????????????ڵ?
	
	/**
	 * ?????жϵ??????????ĺ????Ƿ??????????????ƥ??
	 * @param obj ???????
	 * @return true??????Ľڵ??????????????ƥ?䣬?????Ա???Ա??????false??????
	 */
	abstract public boolean isLeftTypeMatch(Object obj);
	
	/**
	 * ???õ?????????????󵽵?ǰ????
	 * @param obj ???????
	 */
	abstract public void setDotLeftObject(Object obj);
	
	/**
	 * ???ýڵ?????ڵ?
	 * @param node ?ڵ?
	 */
	public void setLeft(Node node) {
		left = node;
	}

	/**
	 * ȡ?ڵ?????ڵ㣬û?з??ؿ?
	 * @return Node
	 */
	public Node getLeft() {
		return left;
	}

	/**
	 * ???ú???????????????????̳??˴˷?????Ҫ???û???Ĵ˷??????ߵ???next?Ĵ˷???
	 * @param cs ???????
	 * @param ctx ??????????
	 * @param param ?????????ַ???
	 */
	public void setParameter(ICellSet cs, Context ctx, String param) {
		super.setParameter(cs, ctx, param);
		if (next != null) {
			next.setParameter(cs, ctx, param);
		}
	}
	
	public void setOption(String opt) {
		super.setOption(opt);
		if (next != null) {
			next.setOption(opt);
		}
	}

	/**
	 * ȡ??һ??ͬ???ij?Ա??????û???򷵻ؿ?
	 * @return MemberFunction
	 */
	public MemberFunction getNextFunction() {
		return next;
	}
	
	/**
	 * ??????һ??ͬ???ij?Ա????
	 * @param fn ??Ա????
	 */
	public void setNextFunction(MemberFunction fn) {
		next = fn;
	}
	
	/**
	 * ?жϵ?ǰ?ڵ??Ƿ??????к???
	 * ?????????????Ҳ?ڵ??????к????????ڵ?????????????Ҫ????ת??????
	 * @return
	 */
	public boolean isSequenceFunction() {
		// ???ͬ?????????????˴˷?????????ã?????ͷ???Ĭ??ֵ
		return next == null ? false : next.isSequenceFunction();
	}

	/**
	 * ?жϽڵ??Ƿ???޸????еij?Աֵ???˷???Ϊ???Ż?[1,2,3].contain(...)???ֱ???ʽ??
	 * ??????в??ᱻ??????[1,2,3]???Ա??????ɳ??????У???????ÿ?μ??㶼????һ??????
	 * @return true?????޸ģ?false???????޸?
	 */
	public boolean ifModifySequence() {
		// ???ͬ?????????????˴˷?????????ã?????ͷ???Ĭ??ֵ
		return next == null ? true : next.isSequenceFunction();
	}
	
	/**
	 * ?Խڵ????Ż?
	 * @param ctx ??????????
	 * @param Node ?Ż???Ľڵ?
	 */
	public Node optimize(Context ctx) {
		if (param != null) {
			// ?Բ??????Ż?
			param.optimize(ctx);
			if (next != null) {
				next.optimize(ctx);
			}
		}
		
		return this;
	}
	
	// x:??,A:y:??,z:F,??
	protected static void parseJoinParam(IParam param, int index, Expression[][] exps,
								   Object[] codes, Expression[][] dataExps,
								   Expression[][] newExps, String[][] newNames, Context ctx) {
		int size = param.getSubSize();
		if (size < 2) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("join" + mm.getMessage("function.invalidParam"));
		}

		IParam sub = param.getSub(0);
		if (sub == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("join" + mm.getMessage("function.invalidParam"));
		} else if (sub.isLeaf()) {
			exps[index] = new Expression[]{sub.getLeafExpression()};
		} else {
			int expCount = sub.getSubSize();
			Expression []tmps = new Expression[expCount];
			exps[index] = tmps;

			for (int i = 0; i < expCount; ++i) {
				IParam p = sub.getSub(i);
				if (p == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("join" + mm.getMessage("function.invalidParam"));
				}

				tmps[i] = p.getLeafExpression();
			}
		}

		sub = param.getSub(1);
		if (sub == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("join" + mm.getMessage("function.invalidParam"));
		} else if (sub.isLeaf()) {
			codes[index] = sub.getLeafExpression().calculate(ctx);
		} else {
			IParam p = sub.getSub(0);
			if (p == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("join" + mm.getMessage("function.invalidParam"));
			}

			codes[index] = p.getLeafExpression().calculate(ctx);
			int expCount = sub.getSubSize() - 1;
			Expression []tmps = new Expression[expCount];
			dataExps[index] = tmps;

			for (int i = 0; i < expCount; ++i) {
				p = sub.getSub(i + 1);
				if (p == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("join" + mm.getMessage("function.invalidParam"));
				}

				tmps[i] = p.getLeafExpression();
			}
		}
		
		int expCount = size - 2;
		Expression []tmpExps = new Expression[expCount];
		String []tmpNames = new String[expCount];
		newExps[index] = tmpExps;
		newNames[index] = tmpNames;

		for (int i = 0; i < expCount; ++i) {
			IParam p = param.getSub(i + 2);
			if (p == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("join" + mm.getMessage("function.invalidParam"));
			}

			if (p.isLeaf()) {
				tmpExps[i] = p.getLeafExpression();
			} else {
				if (p.getSubSize() != 2) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("join" + mm.getMessage("function.invalidParam"));
				}

				IParam sub0 = p.getSub(0);
				if (sub0 == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("join" + mm.getMessage("function.invalidParam"));
				}

				tmpExps[i] = sub0.getLeafExpression();
				IParam sub1 = p.getSub(1);
				if (sub1 != null) {
					tmpNames[i] = sub1.getLeafExpression().getIdentifierName();
				}
			}
		}
	}

	// x:??,A:y:??,z:F,??
	protected static void parseJoinxParam(IParam param, int index, Expression[][] exps,  Object[] codes, 
			Expression[][] dataExps, Expression[][] newExps, String[][] newNames, Context ctx) {
		int size = param.getSubSize();
		if (size < 2) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("joinx" + mm.getMessage("function.invalidParam"));
		}

		IParam sub = param.getSub(0);
		if (sub == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("joinx" + mm.getMessage("function.invalidParam"));
		} else if (sub.isLeaf()) {
			exps[index] = new Expression[]{sub.getLeafExpression()};
		} else {
			int expCount = sub.getSubSize();
			Expression []tmps = new Expression[expCount];
			exps[index] = tmps;

			for (int i = 0; i < expCount; ++i) {
				IParam p = sub.getSub(i);
				if (p == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("joinx" + mm.getMessage("function.invalidParam"));
				}

				tmps[i] = p.getLeafExpression();
			}
		}

		sub = param.getSub(1);
		if (sub == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("joinx" + mm.getMessage("function.invalidParam"));
		} else if (sub.isLeaf()) {
			codes[index] = sub.getLeafExpression().calculate(ctx);
		} else {
			IParam p = sub.getSub(0);
			if (p == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("joinx" + mm.getMessage("function.invalidParam"));
			}

			codes[index] = p.getLeafExpression().calculate(ctx);
			int expCount = sub.getSubSize() - 1;
			Expression []tmps = new Expression[expCount];
			dataExps[index] = tmps;

			for (int i = 0; i < expCount; ++i) {
				p = sub.getSub(i + 1);
				if (p == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("joinx" + mm.getMessage("function.invalidParam"));
				}

				tmps[i] = p.getLeafExpression();
			}
		}
		
		int expCount = size - 2;
		Expression []tmpExps = new Expression[expCount];
		String []tmpNames = new String[expCount];
		newExps[index] = tmpExps;
		newNames[index] = tmpNames;

		for (int i = 0; i < expCount; ++i) {
			IParam p = param.getSub(i + 2);
			if (p == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("joinx" + mm.getMessage("function.invalidParam"));
			}

			if (p.isLeaf()) {
				tmpExps[i] = p.getLeafExpression();
			} else {
				if (p.getSubSize() != 2) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("joinx" + mm.getMessage("function.invalidParam"));
				}

				IParam sub0 = p.getSub(0);
				if (sub0 == null) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("joinx" + mm.getMessage("function.invalidParam"));
				}

				tmpExps[i] = sub0.getLeafExpression();
				IParam sub1 = p.getSub(1);
				if (sub1 != null) {
					tmpNames[i] = sub1.getLeafExpression().getIdentifierName();
				}
			}
		}
	}

	protected static void parseSwitchParam(IParam param, int i, 
			String []fkNames, Object []codes, Expression []exps, Context ctx) {
		if (param == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("switch" + mm.getMessage("function.missingParam"));
		} else if (param.isLeaf()) {
			fkNames[i] = param.getLeafExpression().getIdentifierName();
			return;
		}
		
		int size = param.getSubSize();
		if (size > 3) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("switch" + mm.getMessage("function.invalidParam"));
		}
		
		IParam sub = param.getSub(0);
		if (sub == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("switch" + mm.getMessage("function.invalidParam"));
		}
		
		fkNames[i] = sub.getLeafExpression().getIdentifierName();
		sub = param.getSub(1);
		if (sub == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("switch" + mm.getMessage("function.invalidParam"));
		} else if (sub.isLeaf()) {
			codes[i] = sub.getLeafExpression().calculate(ctx);
			if (codes[i] == null) {
				codes[i] = new Sequence();
			}
			
			if (size > 2) {
				sub = param.getSub(2);
				if (sub != null) {
					exps[i] = sub.getLeafExpression();
				}
			}
		} else {
			if (sub.getSubSize() != 2 || size > 2) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("switch" + mm.getMessage("function.invalidParam"));
			}
			
			IParam sub0 = sub.getSub(0);
			if (sub0 == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("switch" + mm.getMessage("function.invalidParam"));
			}
			
			codes[i] = sub0.getLeafExpression().calculate(ctx);
			if (codes[i] == null) {
				codes[i] = new Sequence();
			}

			IParam sub1 = sub.getSub(1);
			if (sub1 != null) {
				exps[i] = sub1.getLeafExpression();
			}
		}
	}
	
	// F:FT,A:x:xt
	protected static void parseSwitchParam(IParam param, int i,  String []fkNames, String []timeFkNames, 
			Object []codes, Expression []exps, Expression []timeExps, Context ctx) {
		if (param == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("switch" + mm.getMessage("function.missingParam"));
		} else if (param.isLeaf()) {
			fkNames[i] = param.getLeafExpression().getIdentifierName();
			return;
		} else if (param.getSubSize() != 2 || param.getType() != IParam.Comma) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("switch" + mm.getMessage("function.invalidParam"));
		}
		
		IParam sub = param.getSub(0);
		if (sub == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("switch" + mm.getMessage("function.invalidParam"));
		} else if (sub.isLeaf()) {
			fkNames[i] = sub.getLeafExpression().getIdentifierName();
		} else if (sub.getSubSize() == 2) {
			IParam sub0 = sub.getSub(0);
			IParam sub1 = sub.getSub(1);
			if (sub0 == null || sub1 == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("switch" + mm.getMessage("function.invalidParam"));
			}
			
			fkNames[i] = sub0.getLeafExpression().getIdentifierName();
			timeFkNames[i] = sub1.getLeafExpression().getIdentifierName();
		} else {
			MessageManager mm = EngineMessage.get();
			throw new RQException("switch" + mm.getMessage("function.invalidParam"));
		}
		
		sub = param.getSub(1);
		if (sub == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("switch" + mm.getMessage("function.invalidParam"));
		} else if (sub.isLeaf()) {
			codes[i] = sub.getLeafExpression().calculate(ctx);
			if (codes[i] == null) {
				codes[i] = new Sequence();
			}
		} else {
			int size = sub.getSubSize();
			if (size > 3) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("switch" + mm.getMessage("function.invalidParam"));
			}
			
			IParam sub0 = sub.getSub(0);
			if (sub0 == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("switch" + mm.getMessage("function.invalidParam"));
			}
			
			codes[i] = sub0.getLeafExpression().calculate(ctx);
			if (codes[i] == null) {
				codes[i] = new Sequence();
			}

			IParam sub1 = sub.getSub(1);
			if (sub1 != null) {
				exps[i] = sub1.getLeafExpression();
			}
			
			if (size > 2) {
				IParam sub2 = sub.getSub(2);
				if (sub2 != null) {
					timeExps[i] = sub2.getLeafExpression();
				}
			}
		}
	}
	
	protected IArray calculateAll(IArray leftArray, Context ctx) {
		Current current = ctx.getComputeStack().getTopCurrent();
		int len = current.length();
		ObjectArray array = new ObjectArray(len);
		array.setTemporary(true);
		
		Next:
		for (int i = 1; i <= len; ++i) {
			current.setCurrent(i);
			Object leftValue = leftArray.get(i);
			
			if (leftValue == null) {
				array.push(null);
			} else {
				if (leftValue instanceof Number && isSequenceFunction()) {
					int n = ((Number)leftValue).intValue();
					if (n > 0) {
						leftValue = new Sequence(1, n);
					} else {
						leftValue = new Sequence(0);
					}
				}
				
				for (MemberFunction right = this; right != null; right = right.getNextFunction()) {
					if (right.isLeftTypeMatch(leftValue)) {
						right.setDotLeftObject(leftValue);
						Object value = right.calculate(ctx);
						array.push(value);
						continue Next;
					}
				}
				
				String fnName = getFunctionName();
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("dot.leftTypeError", Variant.getDataType(leftValue), fnName));
			}
		}
		
		return array;
	}
	
	protected BoolArray calculateAnd(IArray leftArray, Context ctx, IArray leftResult) {
		Current current = ctx.getComputeStack().getTopCurrent();
		int len = current.length();
		BoolArray result = leftResult.isTrue();
		
		Next:
		for (int i = 1; i <= len; ++i) {
			if (leftResult.isTrue(i)) {
				current.setCurrent(i);
				Object leftValue = leftArray.get(i);
				if (leftValue == null) {
					result.set(i, false);
				} else {
					if (leftValue instanceof Number && isSequenceFunction()) {
						int n = ((Number)leftValue).intValue();
						if (n > 0) {
							leftValue = new Sequence(1, n);
						} else {
							leftValue = new Sequence(0);
						}
					}
					
					for (MemberFunction right = this; right != null; right = right.getNextFunction()) {
						if (right.isLeftTypeMatch(leftValue)) {
							right.setDotLeftObject(leftValue);
							Object value = right.calculate(ctx);
							if (Variant.isFalse(value)) {
								result.set(i, false);
							}

							continue Next;
						}
					}
					
					String fnName = getFunctionName();
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("dot.leftTypeError", Variant.getDataType(leftValue), fnName));
				}
			}
		}
		
		return result;
	}
	
	protected IArray calculateAll(IArray leftArray, Context ctx, IArray signArray, boolean sign) {
		int size = signArray.size();
		ObjectArray result = new ObjectArray(size);
		result.setTemporary(true);
		Current current = ctx.getComputeStack().getTopCurrent();
		
		Next:
		for (int i = 1; i <= size; ++i) {
			if (signArray.isTrue(i) == sign) {
				current.setCurrent(i);
				Object leftValue = leftArray.get(i);
				
				if (leftValue == null) {
					result.push(null);
				} else {
					if (leftValue instanceof Number && isSequenceFunction()) {
						int n = ((Number)leftValue).intValue();
						if (n > 0) {
							leftValue = new Sequence(1, n);
						} else {
							leftValue = new Sequence(0);
						}
					}
					
					for (MemberFunction right = this; right != null; right = right.getNextFunction()) {
						if (right.isLeftTypeMatch(leftValue)) {
							right.setDotLeftObject(leftValue);
							Object value = right.calculate(ctx);
							result.push(value);
							continue Next;
						}
					}
					
					String fnName = getFunctionName();
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("dot.leftTypeError", Variant.getDataType(leftValue), fnName));
				}
			} else {
				result.push(null);
			}
		}
		
		return result;
	}
	
	/**
	 * ??????????еĽ??
	 * @param left ????????????ڵ?
	 * @param ctx ??????????
	 * @return IArray
	 */
	public IArray calculateAll(Context ctx) {
		return calculateAll(left.calculateAll(ctx), ctx);
	}
	
	/**
	 * ????signArray??ȡֵΪsign????
	 * @param ctx
	 * @param signArray ?б?ʶ????
	 * @param sign ??ʶ
	 * @return IArray
	 */
	public IArray calculateAll(Context ctx, IArray signArray, boolean sign) {
		IArray leftArray = left.calculateAll(ctx, signArray, sign);
		return calculateAll(leftArray, ctx, signArray, sign);

		/*Node left = this.left;
		int size = signArray.size();
		ObjectArray result = new ObjectArray(size);
		result.setTemporary(true);
		Current current = ctx.getComputeStack().getTopCurrent();
		
		Next:
		for (int i = 1; i <= size; ++i) {
			if (signArray.isTrue(i) == sign) {
				current.setCurrent(i);
				Object leftValue = left.calculate(ctx);
				
				if (leftValue == null) {
					result.push(null);
				} else {
					if (leftValue instanceof Number && isSequenceFunction()) {
						int n = ((Number)leftValue).intValue();
						if (n > 0) {
							leftValue = new Sequence(1, n);
						} else {
							leftValue = new Sequence(0);
						}
					}
					
					for (MemberFunction right = this; right != null; right = right.getNextFunction()) {
						if (right.isLeftTypeMatch(leftValue)) {
							right.setDotLeftObject(leftValue);
							Object value = right.calculate(ctx);
							result.push(value);
							continue Next;
						}
					}
					
					String fnName = getFunctionName();
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("dot.leftTypeError", Variant.getDataType(leftValue), fnName));
				}
			} else {
				result.push(null);
			}
		}
		
		return result;*/
	}
	
	/**
	 * ?????߼????????&&???Ҳ????ʽ
	 * @param ctx ??????????
	 * @param leftResult &&??????ʽ?ļ?????
	 * @return BoolArray
	 */
	public BoolArray calculateAnd(Context ctx, IArray leftResult) {
		IArray leftArray = left.calculateAll(ctx, leftResult, true);
		return calculateAnd(leftArray, ctx, leftResult);
		
		/*Node left = this.left;
		BoolArray result = leftResult.isTrue();
		int size = result.size();
		Current current = ctx.getComputeStack().getTopCurrent();
		
		Next:
		for (int i = 1; i <= size; ++i) {
			if (result.isTrue(i)) {
				current.setCurrent(i);
				Object leftValue = left.calculate(ctx);
				
				if (leftValue == null) {
					result.set(i, false);
				} else {
					if (leftValue instanceof Number && isSequenceFunction()) {
						int n = ((Number)leftValue).intValue();
						if (n > 0) {
							leftValue = new Sequence(1, n);
						} else {
							leftValue = new Sequence(0);
						}
					}
					
					for (MemberFunction right = this; right != null; right = right.getNextFunction()) {
						if (right.isLeftTypeMatch(leftValue)) {
							right.setDotLeftObject(leftValue);
							Object value = right.calculate(ctx);
							if (Variant.isFalse(value)) {
								result.set(i, false);
							}

							continue Next;
						}
					}
					
					String fnName = getFunctionName();
					MessageManager mm = EngineMessage.get();
					throw new RQException(mm.getMessage("dot.leftTypeError", Variant.getDataType(leftValue), fnName));
				}
			}
		}
		
		return result;*/
	}
		
	/**
	 * ?жϸ?????ֵ??Χ?Ƿ????㵱ǰ????????ʽ
	 * @param ctx ??????????
	 * @return ȡֵ????Relation. -1??ֵ??Χ??û????????????ֵ??0??ֵ??Χ??????????????ֵ??1??ֵ??Χ??ֵ??????????
	 */
	/*public int isValueRangeMatch(Context ctx) {
		IArray array = left.calculateRange(ctx);
		if (!(array instanceof ConstArray)) {
			return Relation.PARTICALMATCH;
		}
		
		Object leftValue = array.get(1);
		if (leftValue instanceof Number && isSequenceFunction()) {
			int n = ((Number)leftValue).intValue();
			if (n > 0) {
				leftValue = new Sequence(1, n);
			} else {
				leftValue = new Sequence(0);
			}
		}
		
		for (MemberFunction right = this; right != null; right = right.getNextFunction()) {
			if (right.isLeftTypeMatch(leftValue)) {
				right.setDotLeftObject(leftValue);
				return right.isValueRangeMatch(ctx);
			}
		}
		
		return Relation.PARTICALMATCH;
	}*/
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy