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

com.scudata.expression.fn.Get Maven / Gradle / Ivy

Go to download

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

There is a newer version: 20240823
Show newest version
package com.scudata.expression.fn;

import com.scudata.array.ConstArray;
import com.scudata.array.IArray;
import com.scudata.array.ObjectArray;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.BaseRecord;
import com.scudata.dm.ComputeStack;
import com.scudata.dm.Context;
import com.scudata.dm.Current;
import com.scudata.dm.DataStruct;
import com.scudata.dm.IComputeItem;
import com.scudata.dm.KeyWord;
import com.scudata.dm.LinkEntry;
import com.scudata.dm.Sequence;
import com.scudata.expression.Function;
import com.scudata.expression.IParam;
import com.scudata.expression.Move;
import com.scudata.expression.Node;
import com.scudata.resources.EngineMessage;

/**
 * ѭ???????е??????㣬??????ͬ?ֶ?ֵ?ij?Ա?ۻ?
 * get(level,F;a:b) ?ڶ??ѭ????????ȡ???ϲ?Ļ???Ա??Ϣ??????A.fn(B.fn(get(1))????ʾȡA?ĵ?ǰѭ????Ա
 * 					levelΪ???????IJ?????????Ϊ0??
 * 					FΪ?ֶ?????#??ʾ??ţ?ʡ??ȡ??Ա??
 * 					a:b?????????[??]??ͬ????ʡ?ԣ???ѭ?????????޶???
 * @author runqian
 *
 */
public class Get extends Function {
	private int level = -1;
	private String fieldName; // ??Ҫȡ???ֶΣ????û??F??????Ϊ??
	private boolean isSeq; // ?Ƿ?ȡ??ǰѭ????ţ????fieldNameΪ?ղ???isSeqΪfalse??ȡ??ǰѭ????Ա
	private IParam moveParam;
	
	private DataStruct prevDs; // ?ϴμ????Ӧ?????ݽṹ???????????Ż?
	private int col = -1; // ?ϴμ????Ӧ???ֶ????????????????Ż?
	
	public Node optimize(Context ctx) {
		if (param != null) param.optimize(ctx);
		return this;
	}
	
	private void prepare(IParam param, Context ctx) {
		if (param != null && param.getType() == IParam.Semicolon) {
			moveParam = param.getSub(1);
			param = param.getSub(0);
		}
		
		if (param == null) {
			level = 0;
		} else if (param.isLeaf()) {
			Object obj = param.getLeafExpression().calculate(ctx);
			if (obj instanceof Number) {
				level = ((Number)obj).intValue();
				if (level < 0) {
					MessageManager mm = EngineMessage.get();
					throw new RQException("get" + mm.getMessage("function.missingParam"));
				}
			} else {
				MessageManager mm = EngineMessage.get();
				throw new RQException("get" + mm.getMessage("function.paramTypeError"));
			}
		} else if (param.getSubSize() == 2) {
			IParam levelParam = param.getSub(0);
			if (levelParam == null) {
				level = 0;
			} else {
				Object obj = levelParam.getLeafExpression().calculate(ctx);
				if (obj instanceof Number) {
					level = ((Number)obj).intValue();
					if (level < 0) {
						MessageManager mm = EngineMessage.get();
						throw new RQException("get" + mm.getMessage("function.missingParam"));
					}
				} else {
					MessageManager mm = EngineMessage.get();
					throw new RQException("get" + mm.getMessage("function.paramTypeError"));
				}
			}
			
			IParam fieldParam = param.getSub(1);
			if (fieldParam == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("get" + mm.getMessage("function.invalidParam"));
			}
			
			fieldName = fieldParam.getLeafExpression().getIdentifierName();
			isSeq = fieldName.equals(KeyWord.CURRENTSEQ);
		} else {
			MessageManager mm = EngineMessage.get();
			throw new RQException("get" + mm.getMessage("function.invalidParam"));
		}
	}
	
	public Object calculate(Context ctx) {
		if (level == -1) {
			prepare(param, ctx);
		}
		
		ComputeStack stack = ctx.getComputeStack();
		LinkEntry entry = stack.getStackHeadEntry();
		if (entry == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException(mm.getMessage("function.notInCyclicalFunction", "'get'"));
		}
		
		// ???ݲ?ȡ????Ӧ??ѭ??????
		int level = this.level;
		while (level != 0) {
			level--;
			entry = entry.getNext();
			if (entry == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException(this.level + mm.getMessage("engine.indexOutofBound"));
			}
		}
		
		IComputeItem item = entry.getElement();
		if (moveParam == null) {
			// get(level,F)
			if (fieldName == null) {
				return item.getCurrent();
			} else if (isSeq) {
				return item.getCurrentIndex();
			} else {
				Object obj = item.getCurrent();
				return getFieldValue(obj);
			}
		} else {
			// get(level,F;a:b)
			if (!(item instanceof Current)) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("get" + mm.getMessage("function.invalidParam"));
			}
			
			Current current = (Current)item;
			if (moveParam.isLeaf()) {
				int pos = Move.calculateIndex(current, moveParam, ctx);
				if (fieldName == null) {
					return pos > 0 ? current.get(pos) : null;
				} else if (isSeq) {
					return pos;
				} else {
					if (pos < 1) {
						return null;
					}
					
					Object obj = current.get(pos);
					return getFieldValue(obj);
				}
			} else {
				int []range = Move.calculateIndexRange(current, moveParam, ctx);
				if (range == null) {
					return new Sequence(0);
				}
				
				if (fieldName == null) {
					int startSeq = range[0];
					int endSeq = range[1];
					Sequence result = new Sequence(endSeq - startSeq + 1);
					for (; startSeq <= endSeq; ++startSeq) {
						result.add(current.get(startSeq));
					}

					return result;
				} else if (isSeq) {
					return new Sequence(range[0], range[1]);
				} else {
					return Move.getFieldValues(current, fieldName, range[0], range[1]);
				}
			}
		}
	}
	
	// ȡobj??fieldName?ֶ?ֵ
	private Object getFieldValue(Object obj) {
		if (obj instanceof BaseRecord) {
			BaseRecord cur = (BaseRecord)obj;
			if (prevDs != cur.dataStruct()) {
				prevDs = cur.dataStruct();
				col = prevDs.getFieldIndex(fieldName);
				if (col < 0) {
					MessageManager mm = EngineMessage.get();
					throw new RQException(fieldName + mm.getMessage("ds.fieldNotExist"));
				}
			}

			return cur.getNormalFieldValue(col);
		} else if (obj instanceof Sequence) {
			// ?????ǰԪ??????????ȡ???һ??Ԫ??
			if (((Sequence)obj).length() == 0) {
				return null;
			}
			
			obj = ((Sequence)obj).get(1);
			if (obj instanceof BaseRecord) {
				BaseRecord cur = (BaseRecord)obj;
				if (prevDs != cur.dataStruct()) {
					prevDs = cur.dataStruct();
					col = prevDs.getFieldIndex(fieldName);
					if (col < 0) {
						MessageManager mm = EngineMessage.get();
						throw new RQException(fieldName + mm.getMessage("ds.fieldNotExist"));
					}
				}

				return cur.getNormalFieldValue(col);
			} else if (obj == null) {
				return null;
			} else {
				MessageManager mm = EngineMessage.get();
				throw new RQException(mm.getMessage("Expression.unknownExpression") + fieldName);
			}
		} else if (obj == null) {
			return null;
		} else {
			MessageManager mm = EngineMessage.get();
			throw new RQException(mm.getMessage("Expression.unknownExpression") + fieldName);
		}
	}
	
	/**
	 * ??????????еĽ??
	 * @param ctx ??????????
	 * @return IArray
	 */
	public IArray calculateAll(Context ctx) {
		if (level == -1) {
			prepare(param, ctx);
		}
		
		Current current = ctx.getComputeStack().getTopCurrent();
		int len = current.length();

		if (level != 0 && moveParam == null) {
			Object value = calculate(ctx);
			return new ConstArray(value, len);
		} else {
			ObjectArray array = new ObjectArray(len);
			array.setTemporary(true);
			
			for (int i = 1; i <= len; ++i) {
				current.setCurrent(i);
				Object value = calculate(ctx);
				array.push(value);
			}
			
			return array;
		}
	}

	/**
	 * ????signArray??ȡֵΪsign????
	 * @param ctx
	 * @param signArray ?б?ʶ????
	 * @param sign ??ʶ
	 * @return IArray
	 */
	public IArray calculateAll(Context ctx, IArray signArray, boolean sign) {
		return calculateAll(ctx);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy