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

com.scudata.expression.fn.gather.Top 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.fn.gather;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

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.Env;
import com.scudata.dm.Sequence;
import com.scudata.dm.comparator.ArrayComparator;
import com.scudata.dm.comparator.BaseComparator;
import com.scudata.dm.comparator.DescComparator;
import com.scudata.expression.CurrentElement;
import com.scudata.expression.Expression;
import com.scudata.expression.Gather;
import com.scudata.expression.IParam;
import com.scudata.resources.EngineMessage;
import com.scudata.util.MinHeap;

/**
 * ȡ????ǰ????Ԫ??
 * top(n,x) top(n;x,??) top(n,y,x)
 * @author RunQian
 *
 */
public class Top extends Gather {
	private int count = 1;
	private Expression exp; // ?Ƚϱ???ʽ
	private Expression getExp; // ?????ȡֵ????ʽ
	private boolean isCurrent; // ?Ƿ?ȡ??ǰ??¼
	
	private boolean isPositive = true; // n?Ƿ???????
	private boolean isOne = false; // ?Ƿ???@1ѡ??
	private boolean isSame = false; // ?Ƿ?ȡ??????????С??
	private boolean isRank = false; // ?Ƿ?????????ʽȡǰ??
	private boolean isDistinct = false; // ?Ƿ?ȥ?ط?ʽ??????
	
	private Comparator comparator;
	private int expIndex = -1; // ?Ƚϱ???ʽ???ֶ?????

	public void prepare(Context ctx) {
		if (option != null) {
			if (option.indexOf('1') != -1) isOne = true;
			if (option.indexOf('i') != -1) {
				isRank = true;
				isDistinct = true;
			} else if (option.indexOf('r') != -1) {
				isRank = true;
			}
		}
		
		if (param == null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("top" + mm.getMessage("function.missingParam"));
		} else if (param.isLeaf()) {
			Object obj = param.getLeafExpression().calculate(ctx);
			if (obj instanceof Number) {
				count = ((Number)obj).intValue();
			} else if (obj != null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("top" + mm.getMessage("function.paramTypeError"));
			}
		} else if (param.getType() == IParam.Semicolon) {
			if (param.getSubSize() != 2) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("top" + mm.getMessage("function.invalidParam"));
			}
			
			IParam sub0 = param.getSub(0);
			IParam sub1 = param.getSub(1);
			if (sub0 == null || sub1 == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("top" + mm.getMessage("function.invalidParam"));
			}
			
			Object obj = sub0.getLeafExpression().calculate(ctx);
			if (obj instanceof Number) {
				count = ((Number)obj).intValue();
			} else if (obj != null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("top" + mm.getMessage("function.paramTypeError"));
			}
			
			if (sub1.isLeaf()) {
				exp = sub1.getLeafExpression();
			} else {
				//ValueList valueList = new ValueList();
				//valueList.setParam(sub1);
				//exp = new Expression(valueList);
				
				String []strs = sub1.toStringArray("top", false);
				StringBuffer sb = new StringBuffer(64);
				sb.append('[');
				for (int i = 0; i < strs.length; ++i) {
					if (i > 0) {
						sb.append(',');
					}
					
					sb.append(strs[i]);
				}
				
				sb.append(']');
				exp = new Expression(cs, ctx, sb.toString());
			}
			
			getExp = new Expression(ctx, "~");
			isCurrent = true;
		} else {
			int size = param.getSubSize();
			if (size > 3) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("top" + mm.getMessage("function.invalidParam"));
			}
			
			IParam sub0 = param.getSub(0);
			if (sub0 == null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("top" + mm.getMessage("function.invalidParam"));
			}
			
			Object obj = sub0.getLeafExpression().calculate(ctx);
			if (obj instanceof Number) {
				count = ((Number)obj).intValue();
			} else if (obj != null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("top" + mm.getMessage("function.paramTypeError"));
			}
			
			IParam sub1 = param.getSub(1);
			if (sub1 != null) exp = sub1.getLeafExpression();
			
			if (size > 2) {
				IParam sub2 = param.getSub(2);
				if (sub2 != null) {
					getExp = sub2.getLeafExpression();
					if (getExp.getHome() instanceof CurrentElement) {
						isCurrent = true;
					}
				}
			}
		}

		if (exp == null) {
			exp = new Expression(ctx, "~");
		} else if (exp.isConstExpression()) {
			exp = null;
		}
		
		if (count == 0) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("top" + mm.getMessage("function.invalidParam"));
		} else if (count < 0) {
			count = -count;
			isPositive = false;
		}
		
		if (count == 1 && !isOne && exp != null) {
			isSame = true;
		}
		
		if (exp != null) {
			if (getExp != null) {
				comparator = new ArrayComparator(1);
			} else {
				comparator = new BaseComparator();
			}
			
			if (!isPositive) {
				comparator = new DescComparator(comparator);
			}
		}
	}
	
	public Expression getRegatherExpression(int q) {
		String str = "top@2";
		if (option != null) {
			str += option;
		}
		
		if (isPositive) {
			str += "(";
		} else {
			str += "(-";
		}
		
		if (exp == null) { // top(n,0) -> top(n,0,#q)
			str += count + ",0,#" + q + ')';
		} else if (getExp == null) { // top(n,x) -> top(n, ~, #q)
			str += count + ",~,#" + q + ')';
		} else { // top(n,x, y) -> top(n, x, #q)
			str += count + "," + exp.toString() + ",#" + q + ')';
		}
		
		return new Expression(str);
	}

	public int getCount() {
		return count;
	}

	public Expression getExp() {
		return exp;
	}

	public Expression getGetExp() {
		return getExp;
	}

	public boolean isCurrent() {
		return isCurrent;
	}

	public boolean isOne() {
		return isOne;
	}

	public boolean isSame() {
		return isSame;
	}

	public Comparator getComparator() {
		return comparator;
	}

	public int getExpIndex() {
		return expIndex;
	}
	
	public Object calculate(Context ctx) {
		MessageManager mm = EngineMessage.get();
		throw new RQException(mm.getMessage("Expression.unknownFunction") + "top");
	}
	
	public boolean isPositive() {
		return isPositive;
	}

	public boolean needFinish() {
		return !isSame || getExp != null || isRank;
	}
	
	public boolean needFinish1() {
		return !isSame || getExp != null || isRank;
	}

	public Object finish1(Object val) {
		return finish(val);
	}
	
	public IArray finish1(IArray array) {
		return finish(array);
	}
	
	public IArray finish(IArray array) {
		int size = array.size();
		if (isRank) {
			for (int i = 1; i <= size; ++i) {
				RankArray rankArray = (RankArray)array.get(i);
				ObjectArray valueArray = rankArray.getValueArray();
				
				if (getExp != null) {
					for (int v = 1, vcount = valueArray.size(); v <= vcount; ++v) {
						Object []tmp = (Object[])valueArray.get(v);
						valueArray.set(v, tmp[1]);
					}
				}
				
				array.set(i, new Sequence(valueArray));
			}
		} else if (isSame) {
			for (int i = 1; i <= size; ++i) {
				Sequence seq = (Sequence)array.get(i);
				if (seq != null) {
					IArray mems = seq.getMems();
					for (int m = 1, len = mems.size(); m <= len; ++m) {
						Object []tmp = (Object[])seq.getMem(m);
						mems.set(m, tmp[1]);
					}
				}
			}
		} else if (exp != null) {
			boolean ifOne = count == 1 && isOne;
			for (int i = 1; i <= size; ++i) {
				MinHeap heap = (MinHeap)array.get(i);
				int len = heap.size();
				if (len == 0) {
					array.set(i, null);
				} else if (ifOne) {
					Object obj = heap.getTop();
					if (getExp == null) {
						array.set(i, obj);
					} else {
						Object []tmp = (Object[])obj;
						array.set(i, tmp[1]);
					}
				} else {
					Object []objs = heap.toArray();
					Arrays.sort(objs, comparator);
					
					if (getExp == null) {
						array.set(i, new Sequence(objs));
					} else {
						Sequence seq = new Sequence(len);
						for (int m = 0; m < len; ++m) {
							Object []tmp = (Object[])objs[m];
							seq.add(tmp[1]);
						}
						
						array.set(i, seq);
					}
				}
			}
		} else {
			boolean ifOne = count == 1 && isOne;
			for (int i = 1; i <= size; ++i) {
				List list = (List)array.get(i);
				if (list.size() == 0) {
					array.set(i, null);
				} else if (ifOne) {
					array.set(i, list.get(0));
				} else {
					array.set(i, new Sequence(list.toArray()));
				}
			}
		}
		
		return array;
	}
	
	public Object finish(Object val) {
		if (val == null) {
			return null;
		} else if (isRank) {
			ObjectArray array = ((RankArray)val).getValueArray();
			
			if (getExp != null) {
				for (int i = 1, size = array.size(); i <= size; ++i) {
					Object []tmp = (Object[])array.get(i);
					array.set(i, tmp[1]);
				}
			}
			
			return new Sequence(array);
		} else if (isSame) {
			if (val instanceof Sequence) {
				Sequence seq = (Sequence)val;
				for (int i = 1, size = seq.length(); i <= size; ++i) {
					Object []tmp = (Object[])seq.getMem(i);
					seq.set(i, tmp[1]);
				}
				
				return seq;
			}

			return val;
		} else if (exp != null) {
			MinHeap heap = (MinHeap)val;
			int size = heap.size();
			if (size == 0) return null;
			
			if (count == 1 && isOne) {
				Object obj = heap.getTop();
				if (getExp == null) {
					return obj;
				} else {
					Object []tmp = (Object[])obj;
					return tmp[1];
				}
			} else {
				Object []objs = heap.toArray();
				Arrays.sort(objs, comparator);
				
				if (getExp == null) {
					return new Sequence(objs);
				} else {
					Sequence seq = new Sequence(size);
					for (int i = 0; i < size; ++i) {
						Object []tmp = (Object[])objs[i];
						seq.add(tmp[1]);
					}
					
					return seq;
				}
			}
		} else {
			List list = (List)val;
			if (list.size() == 0) return null;
			
			if (count == 1 && isOne) {
				return list.get(0);
			} else {
				return new Sequence(list.toArray());
			}
		}
	}
	
	// ????top(1,x)ȡ??????????С??
	private static void addToSequence(Sequence seq, Object obj, Comparator comparator) {
		if (obj == null) {
			return;
		} else {
			if (seq.length() == 0) {
				seq.add(obj);
			} else {
				int cmp = comparator.compare(seq.getMem(1), obj);
				if (cmp > 0) {
					seq.clear();
					seq.add(obj);
				} else if (cmp == 0) {
					seq.add(obj);
				}
			}
		}
	}
	
	private static void addToSequence(Sequence seq, Object obj, Expression exp, Context ctx, Comparator comparator) {
		ComputeStack stack = ctx.getComputeStack();
		try {
			if (obj instanceof Sequence) {
				Sequence tmpSeq = (Sequence)obj;
				Current current = new Current(tmpSeq);
				stack.push(current);
				
				for (int i = 1, len = tmpSeq.length(); i <= len; ++i) {
					current.setCurrent(i);
					Object val = exp.calculate(ctx);
					
					if (val != null) {
						Object []vals = new Object[2];
						vals[0] = exp.calculate(ctx);
						vals[1] = current.getCurrent();
						
						if (seq.length() == 0) {
							seq.add(vals);
						} else {
							int cmp = comparator.compare(seq.getMem(1), vals);
							if (cmp > 0) {
								seq.clear();
								seq.add(vals);
							} else if (cmp == 0) {
								seq.add(vals);
							}
						}
					}
				}
			} else if (obj instanceof BaseRecord) {
				stack.push((BaseRecord)obj);
				Object val = exp.calculate(ctx);
				
				if (val != null) {
					Object []vals = new Object[2];
					vals[0] = val;
					vals[1] = obj;
					
					if (seq.length() == 0) {
						seq.add(vals);
					} else {
						int cmp = comparator.compare(seq.getMem(1), vals);
						if (cmp > 0) {
							seq.clear();
							seq.add(vals);
						} else if (cmp == 0) {
							seq.add(vals);
						}
					}
				}
			} else if (obj != null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("top" + mm.getMessage("function.invalidParam"));
			}
		} finally {
			stack.pop();
		}
	}
	
	private static void addToHeap(MinHeap heap, Object obj) {
		if (obj != null) {
			heap.insert(obj);
		}
	}
	
	private void addToHeap(MinHeap heap, Object obj, Expression exp, Context ctx) {
		if (obj instanceof Sequence) {
			ComputeStack stack = ctx.getComputeStack();
			try {
				Sequence seq = (Sequence)obj;
				Current current = new Current(seq);
				stack.push(current);
				
				for (int i = 1, len = seq.length(); i <= len; ++i) {
					current.setCurrent(i);
					Object val = exp.calculate(ctx);
					
					if (val != null) {
						Object []vals = new Object[2];
						vals[0] = exp.calculate(ctx);
						vals[1] = current.getCurrent();
						heap.insert(vals);
					}
				}
			} finally {
				stack.pop();
			}
		} else if (obj instanceof BaseRecord) {
			if (isCurrent) {
				Object val = exp.calculate(ctx);
				
				if (val != null) {
					Object []vals = new Object[2];
					vals[0] = val;
					vals[1] = obj;
					heap.insert(vals);
				}
			} else {
				ComputeStack stack = ctx.getComputeStack();
				try {
					stack.push((BaseRecord)obj);
					Object val = exp.calculate(ctx);
					
					if (val != null) {
						Object []vals = new Object[2];
						vals[0] = val;
						vals[1] = obj;
						heap.insert(vals);
					}
				} finally {
					stack.pop();
				}
			}
		} else if (obj != null) {
			MessageManager mm = EngineMessage.get();
			throw new RQException("top" + mm.getMessage("function.invalidParam"));
		}
	}
	
	private static void addToHeap(MinHeap heap, Object obj, int expIndex) {
		Object val = ((BaseRecord)obj).getFieldValue(expIndex);
		if (val != null) {
			Object []vals = new Object[2];
			vals[0] = val;
			vals[1] = obj;
			heap.insert(vals);
		}
	}
	
	private static void addToArrayList(ArrayList list, Object obj, int count) {
		int size = list.size();
		if (size == count || obj == null) return;
		
		if (obj instanceof Sequence) {
			Sequence seq = (Sequence)obj;
			IArray mems = seq.getMems();
			int len = mems.size();
			for (int i = 1; i <= len && size < count; ++i) {
				Object m = mems.get(i);
				if (m != null) {
					list.add(m);
					size++;
				}
			}
		} else {
			list.add(obj);
		}
	}
	
	private static void addToLinkedList(LinkedList list, Object obj, int count) {
		if (obj == null) return;
		
		int size = list.size();
		if (obj instanceof Sequence) {
			Sequence seq = (Sequence)obj;
			IArray mems = seq.getMems();
			int len = mems.size();
			for (int i = 1; i <= len; ++i) {
				Object m = mems.get(i);
				if (m != null) {
					if (size == count) {
						list.removeFirst();
					} else {
						size++;
					}
					
					list.add(m);
				}
			}
		} else {
			if (size == count) {
				list.removeFirst();
			}
			
			list.add(obj);
		}
	}
	
	public Object gather(Context ctx) {
		if (count == 0) {
			return null;
		} else if (isRank) {
			RankArray array = new RankArray(count, isDistinct);
			if (getExp == null) {
				Object obj = exp.calculate(ctx);
				addToRankArray(array, obj, comparator);
			} else {
				Object obj = getExp.calculate(ctx);
				addToRankArray(array, obj, exp, ctx, comparator);
			}
			
			return array;
		} else if (isSame) {
			Sequence seq = new Sequence();
			if (getExp == null) {
				Object obj = exp.calculate(ctx);
				addToSequence(seq, obj, comparator);
			} else {
				Object obj = getExp.calculate(ctx);
				addToSequence(seq, obj, exp, ctx, comparator);
			}
			
			return seq;
		} else if (exp != null) {
			MinHeap heap = new MinHeap(count, comparator);
			if (getExp == null) {
				Object obj = exp.calculate(ctx);
				addToHeap(heap, obj);
			} else {
				Object obj = getExp.calculate(ctx);
				if (obj instanceof BaseRecord) {
					expIndex = ((BaseRecord)obj).getFieldIndex(exp.getIdentifierName());
				}
				
				addToHeap(heap, obj, exp, ctx);
			}
			
			return heap;
		} else {
			Object obj;
			if (getExp == null) {
				Object top = ctx.getComputeStack().getTopObject();
				obj = ((Current)top).getCurrent();
			} else {
				obj = getExp.calculate(ctx);
			}

			if (isPositive) {
				ArrayList list = new ArrayList(count);
				addToArrayList(list, obj, count);
				return list;
			} else {
				LinkedList list = new LinkedList();
				addToLinkedList(list, obj, count);
				return list;
			}
		}
	}

	public Object gather(Object oldValue, Context ctx) {
		if (isRank) {
			RankArray array = (RankArray)oldValue;
			if (getExp == null) {
				Object obj = exp.calculate(ctx);
				addToRankArray(array, obj, comparator);
			} else {
				Object obj = getExp.calculate(ctx);
				addToRankArray(array, obj, exp, ctx, comparator);
			}
			
			return array;
		} else if (isSame) {
			Sequence seq;
			if (oldValue != null) {
				seq = (Sequence)oldValue;
			} else {
				seq = new Sequence();
			}
			
			if (getExp == null) {
				Object obj = exp.calculate(ctx);
				addToSequence(seq, obj, comparator);
			} else {
				Object obj = getExp.calculate(ctx);
				addToSequence(seq, obj, exp, ctx, comparator);
			}
			
			return seq;
		} else if (exp != null) {
			if (getExp == null) {
				Object obj = exp.calculate(ctx);
				addToHeap((MinHeap)oldValue, obj);
			} else if (expIndex >= 0) {
				Object obj = getExp.calculate(ctx);
				addToHeap((MinHeap)oldValue, obj, expIndex);
			} else {
				Object obj = getExp.calculate(ctx);
				addToHeap((MinHeap)oldValue, obj, exp, ctx);
			}
		} else {
			Object obj;
			if (getExp == null) {
				Object top = ctx.getComputeStack().getTopObject();
				obj = ((Current)top).getCurrent();
			} else {
				obj = getExp.calculate(ctx);
			}

			if (isPositive) {
				addToArrayList((ArrayList)oldValue, obj, count);
			} else {
				addToLinkedList((LinkedList)oldValue, obj, count);
			}
		}
		
		return oldValue;
	}
	
	// ȡ??????Сֵ
	private IArray minAll(IArray result, int []resultSeqs, Context ctx) {
		Expression exp = this.exp;
		if (result == null) {
			result = new ObjectArray(Env.INITGROUPSIZE);
		}
		
		IArray array = exp.calculateAll(ctx);
		for (int i = 1, len = array.size(); i <= len; ++i) {
			if (result.size() < resultSeqs[i]) {
				if (array.isNull(i)) {
					result.add(null);
				} else {
					IArray resultArray = array.newInstance(8);
					resultArray.push(array, i);
					Sequence seq = new Sequence(resultArray);
					result.add(seq);
				}
			} else if (!array.isNull(i)) {
				Sequence seq = (Sequence)result.get(resultSeqs[i]);
				if (seq == null) {
					IArray resultArray = array.newInstance(8);
					resultArray.push(array, i);
					seq = new Sequence(resultArray);
					result.set(resultSeqs[i], seq);
				} else {
					IArray mems = seq.getMems();
					int cmp = mems.compareTo(1, array, i);
					if (cmp == 0) {
						mems.add(array, i);
					} else if(cmp > 0) {
						mems.clear();
						mems.push(array, i);
					}
				}
			}
		}
		
		return result;
	}
		
	// ȡ????ʹָ??????ʽ??????С?ļ?¼
	private IArray topAll(IArray result, int []resultSeqs, Context ctx) {
		if (result == null) {
			result = new ObjectArray(Env.INITGROUPSIZE);
		}
		
		Expression exp = this.exp;
		Comparator comparator = this.comparator;
		IArray array = getExp.calculateAll(ctx);
		
		for (int i = 1, len = array.size(); i <= len; ++i) {
			if (result.size() < resultSeqs[i]) {
				Sequence seq = new Sequence();
				addToSequence(seq, array.get(i), exp, ctx, comparator);
				result.add(seq);
			} else {
				Sequence seq = (Sequence)result.get(resultSeqs[i]);
				addToSequence(seq, array.get(i), exp, ctx, comparator);
			}
		}
		
		return result;
	}
	
	// ȡ???ֵ
	/*private IArray max(IArray result, int []resultSeqs, Context ctx) {
		Expression exp = this.exp;
		if (getExp == null) {
			IArray array = exp.calculateAll(ctx);
			if (result == null) {
				result = array.newInstance(Env.INITGROUPSIZE);
			}
			
			for (int i = 1, len = array.size(); i <= len; ++i) {
				if (result.size() < resultSeqs[i]) {
					result.add(array, i);
				} else if (!array.isNull(i)) {
					if (result.isNull(resultSeqs[i])) {
						result.set(resultSeqs[i], array, i);
					} else {
						if(result.compareTo(resultSeqs[i], array, i) < 0) {
							result.set(resultSeqs[i], array, i);
						}
					}
				}
			}
		} else {
			if (result == null) {
				result = new ObjectArray(Env.INITGROUPSIZE);
			}
			
			IArray array = getExp.calculateAll(ctx);
			IArray valueArray;
			if (isCurrent) {
				valueArray = exp.calculateAll(ctx);
			} else {
				Sequence seq = new Sequence(array);
				seq = seq.calc(exp, ctx);
				valueArray = seq.getMems();
			}

			for (int i = 1, len = array.size(); i <= len; ++i) {
				if (result.size() < resultSeqs[i]) {
					if (valueArray.isNull(i)) {
						result.add(null);
					} else {
						result.add(array, i);
					}
				} else if (!valueArray.isNull(i)) {
					Object r = result.get(resultSeqs[i]);
					if (r == null) {
						result.set(resultSeqs[i], array, i);
					} else if (r instanceof BaseRecord) {
						Object value = ((BaseRecord)r).calc(exp, ctx);
						int cmp = valueArray.compareTo(i, value);
						if(cmp > 0) {
							result.set(resultSeqs[i], array, i);
						}
					} else if (r instanceof Sequence) {
						Object value = ((Sequence)r).calc(1, exp, ctx);
						int cmp = valueArray.compareTo(i, value);
						if(cmp > 0) {
							result.set(resultSeqs[i], array, i);
						}
					} else {
						MessageManager mm = EngineMessage.get();
						throw new RQException("top" + mm.getMessage("function.paramTypeError"));
					}
				}
			}
		}
		
		return result;
	}
	
	// ȡ??Сֵ
	private IArray min(IArray result, int []resultSeqs, Context ctx) {
		Expression exp = this.exp;
		if (getExp == null) {
			IArray array = exp.calculateAll(ctx);
			if (result == null) {
				result = array.newInstance(Env.INITGROUPSIZE);
			}
			
			for (int i = 1, len = array.size(); i <= len; ++i) {
				if (result.size() < resultSeqs[i]) {
					result.add(array, i);
				} else if (!array.isNull(i)) {
					if (result.isNull(resultSeqs[i])) {
						result.set(resultSeqs[i], array, i);
					} else {
						if(result.compareTo(resultSeqs[i], array, i) > 0) {
							result.set(resultSeqs[i], array, i);
						}
					}
				}
			}
		} else {
			if (result == null) {
				result = new ObjectArray(Env.INITGROUPSIZE);
			}
			
			IArray array = getExp.calculateAll(ctx);
			IArray valueArray;
			if (isCurrent) {
				valueArray = exp.calculateAll(ctx);
			} else {
				Sequence seq = new Sequence(array);
				seq = seq.calc(exp, ctx);
				valueArray = seq.getMems();
			}

			for (int i = 1, len = array.size(); i <= len; ++i) {
				if (result.size() < resultSeqs[i]) {
					if (valueArray.isNull(i)) {
						result.add(null);
					} else {
						result.add(array, i);
					}
				} else if (!valueArray.isNull(i)) {
					Object r = result.get(resultSeqs[i]);
					if (r == null) {
						result.set(resultSeqs[i], array, i);
					} else if (r instanceof BaseRecord) {
						Object value = ((BaseRecord)r).calc(exp, ctx);
						int cmp = valueArray.compareTo(i, value);
						if(cmp < 0) {
							result.set(resultSeqs[i], array, i);
						}
					} else if (r instanceof Sequence) {
						Object value = ((Sequence)r).calc(1, exp, ctx);
						int cmp = valueArray.compareTo(i, value);
						if(cmp < 0) {
							result.set(resultSeqs[i], array, i);
						}
					} else {
						MessageManager mm = EngineMessage.get();
						throw new RQException("top" + mm.getMessage("function.paramTypeError"));
					}
				}
			}
		}
		
		return result;
	}*/
	
	// ȡ????????
	private IArray maxAll(IArray result, int []resultSeqs, Context ctx) {
		Expression exp = this.exp;
		if (result == null) {
			result = new ObjectArray(Env.INITGROUPSIZE);
		}
		
		IArray array = exp.calculateAll(ctx);
		for (int i = 1, len = array.size(); i <= len; ++i) {
			if (result.size() < resultSeqs[i]) {
				if (array.isNull(i)) {
					result.add(null);
				} else {
					IArray resultArray = array.newInstance(8);
					resultArray.push(array, i);
					Sequence seq = new Sequence(resultArray);
					result.add(seq);
				}
			} else if (!array.isNull(i)) {
				Sequence seq = (Sequence)result.get(resultSeqs[i]);
				if (seq == null) {
					IArray resultArray = array.newInstance(8);
					resultArray.push(array, i);
					seq = new Sequence(resultArray);
					result.set(resultSeqs[i], seq);
				} else {
					IArray mems = seq.getMems();
					int cmp = mems.compareTo(1, array, i);
					if (cmp == 0) {
						mems.add(array, i);
					} else if(cmp < 0) {
						mems.clear();
						mems.push(array, i);
					}
				}
			}
		}
		
		return result;
	}
	
	/**
	 * ???????м?¼??ֵ?????ܵ??????????
	 * @param result ???????
	 * @param resultSeqs ÿ????¼??Ӧ?Ľ??????????
	 * @param ctx ??????????
	 * @return IArray ???????
	 */
	public IArray gather(IArray result, int []resultSeqs, Context ctx) {
		if (isRank) {
			Comparator comparator = this.comparator;
			Expression exp = this.exp;
			if (result == null) {
				result = new ObjectArray(Env.INITGROUPSIZE);
			}
			
			if (getExp == null) {
				IArray array;
				if (exp != null) {
					array = exp.calculateAll(ctx);
				} else {
					Sequence topSequence = ctx.getComputeStack().getTopSequence();
					array = topSequence.getMems();
				}
				
				for (int i = 1, len = array.size(); i <= len; ++i) {
					if (result.size() < resultSeqs[i]) {
						RankArray rankArray = new RankArray(count, isDistinct);
						addToRankArray(rankArray, array.get(i), comparator);
						result.add(rankArray);
					} else {
						RankArray rankArray = (RankArray)result.get(resultSeqs[i]);
						addToRankArray(rankArray, array.get(i), comparator);
					}
				}
			} else {
				IArray array = getExp.calculateAll(ctx);
				for (int i = 1, len = array.size(); i <= len; ++i) {
					if (result.size() < resultSeqs[i]) {
						RankArray rankArray = new RankArray(count, isDistinct);
						addToRankArray(rankArray, array.get(i), exp, ctx, comparator);
						result.add(rankArray);
					} else {
						RankArray rankArray = (RankArray)result.get(resultSeqs[i]);
						addToRankArray(rankArray, array.get(i), exp, ctx, comparator);
					}
				}
			}
			
			return result;
		} else if (isSame) {
			if (getExp != null) {
				return topAll(result, resultSeqs, ctx);
			} else if (isPositive) {
				return minAll(result, resultSeqs, ctx);
			} else {
				return maxAll(result, resultSeqs, ctx);
			}
		}

		int count = this.count;
		Expression exp = this.exp;
		Comparator comparator = this.comparator;
		
		if (getExp == null) {
			if (result == null) {
				result = new ObjectArray(Env.INITGROUPSIZE);
			}
			
			if (exp != null) {
				IArray array = exp.calculateAll(ctx);
				for (int i = 1, len = array.size(); i <= len; ++i) {
					if (result.size() < resultSeqs[i]) {
						MinHeap heap = new MinHeap(count, comparator);
						addToHeap(heap, array.get(i));
						result.add(heap);
					} else {
						MinHeap heap = (MinHeap)result.get(resultSeqs[i]);
						addToHeap(heap, array.get(i));
					}
				}
			} else {
				Sequence topSequence = ctx.getComputeStack().getTopSequence();
				IArray array = topSequence.getMems();
				
				if (isPositive) {
					for (int i = 1, len = array.size(); i <= len; ++i) {
						if (result.size() < resultSeqs[i]) {
							ArrayList list = new ArrayList(count);
							addToArrayList(list, array.get(i), count);
							result.add(list);
						} else {
							ArrayList list = (ArrayList)result.get(resultSeqs[i]);
							addToArrayList(list, array.get(i), count);
						}
					}
				} else {
					for (int i = 1, len = array.size(); i <= len; ++i) {
						if (result.size() < resultSeqs[i]) {
							LinkedList list = new LinkedList();
							addToLinkedList(list, array.get(i), count);
							result.add(list);
						} else {
							LinkedList list = (LinkedList)result.get(resultSeqs[i]);
							addToLinkedList(list, array.get(i), count);
						}
					}
				}
			}
		} else {
			IArray array = getExp.calculateAll(ctx);
			if (result == null) {
				result = new ObjectArray(Env.INITGROUPSIZE);
				if (exp != null) {
					Object obj = array.get(1);
					if (obj instanceof BaseRecord) {
						expIndex = ((BaseRecord)obj).getFieldIndex(exp.getIdentifierName());
					}
				}
			}
			
			if (expIndex > -1) {
				int expIndex = this.expIndex;
				for (int i = 1, len = array.size(); i <= len; ++i) {
					if (result.size() < resultSeqs[i]) {
						MinHeap heap = new MinHeap(count, comparator);
						addToHeap(heap, array.get(i), expIndex);
						result.add(heap);
					} else {
						MinHeap heap = (MinHeap)result.get(resultSeqs[i]);
						addToHeap(heap, array.get(i), expIndex);
					}
				}
			} else if (exp != null) {
				Current current = ctx.getComputeStack().getTopCurrent();
				for (int i = 1, len = array.size(); i <= len; ++i) {
					current.setCurrent(i);
					if (result.size() < resultSeqs[i]) {
						MinHeap heap = new MinHeap(count, comparator);
						addToHeap(heap, array.get(i), exp, ctx);
						result.add(heap);
					} else {
						MinHeap heap = (MinHeap)result.get(resultSeqs[i]);
						addToHeap(heap, array.get(i), exp, ctx);
					}
				}
			} else {
				if (isPositive) {
					for (int i = 1, len = array.size(); i <= len; ++i) {
						if (result.size() < resultSeqs[i]) {
							ArrayList list = new ArrayList(count);
							addToArrayList(list, array.get(i), count);
							result.add(list);
						} else {
							ArrayList list = (ArrayList)result.get(resultSeqs[i]);
							addToArrayList(list, array.get(i), count);
						}
					}
				} else {
					for (int i = 1, len = array.size(); i <= len; ++i) {
						if (result.size() < resultSeqs[i]) {
							LinkedList list = new LinkedList();
							addToLinkedList(list, array.get(i), count);
							result.add(list);
						} else {
							LinkedList list = (LinkedList)result.get(resultSeqs[i]);
							addToLinkedList(list, array.get(i), count);
						}
					}
				}
			}
		}

		return result;
	}
	
	private void minAll(IArray result, IArray result2, int []seqs) {
		for (int i = 1, len = result2.size(); i <= len; ++i) {
			if (seqs[i] != 0) {
				Sequence sequence1 = (Sequence)result.get(seqs[i]);
				Sequence sequence2 = (Sequence)result2.get(i);
				if (sequence1 == null) {
					result.set(seqs[i], sequence2);
				} else if (sequence2 != null) {
					int cmp = sequence1.getMems().compareTo(1, sequence2.getMems(), 1);
					if (cmp > 0) {
						result.set(seqs[i], sequence2);
					} else if (cmp == 0) {
						sequence1.addAll(sequence2);
					}
				}
			}
		}
	}
	
	private void maxAll(IArray result, IArray result2, int []seqs) {
		for (int i = 1, len = result2.size(); i <= len; ++i) {
			if (seqs[i] != 0) {
				Sequence sequence1 = (Sequence)result.get(seqs[i]);
				Sequence sequence2 = (Sequence)result2.get(i);
				if (sequence1 == null) {
					result.set(seqs[i], sequence2);
				} else if (sequence2 != null) {
					int cmp = sequence1.getMems().compareTo(1, sequence2.getMems(), 1);
					if (cmp < 0) {
						result.set(seqs[i], sequence2);
					} else if (cmp == 0) {
						sequence1.addAll(sequence2);
					}
				}
			}
		}
	}
	
	// ȡ????ʹָ??????ʽ??????С?ļ?¼
	private void topAll(IArray result, IArray result2, int []seqs, Context ctx) {
		Expression exp = this.exp;
		Comparator comparator = this.comparator;
		
		for (int i = 1, len = result2.size(); i <= len; ++i) {
			if (seqs[i] != 0) {
				Sequence sequence1 = (Sequence)result.get(seqs[i]);
				Sequence sequence2 = (Sequence)result2.get(i);
				if (sequence1 == null) {
					result.set(seqs[i], sequence2);
				} else if (sequence2 != null) {
					int cmp = comparator.compare(sequence1.calc(1, exp, ctx), sequence2.calc(1, exp, ctx));
					if (cmp > 0) {
						result.set(seqs[i], sequence2);
					} else if (cmp == 0) {
						sequence1.addAll(sequence2);
					}
				}
			}
		}
	}
	
	private static void addToArrayList(ArrayList list1, ArrayList list2, int count) {
		int size1 = list1.size();
		if (size1 == count) {
			return;
		}
		
		int diff = count - size1;
		int size2 = list2.size();
		if (size2 < diff) {
			diff = size2;
		}
		
		for (int i = 0; i < diff; ++i) {
			list1.add(list2.get(i));
		}
	}
	
	private static void addToLinkedList(LinkedList list1, LinkedList list2, int count) {
		int size2 = list2.size();
		if (size2 == count) {
			return;
		}
		
		int diff = count - size2;
		int size1 = list1.size();
		if (size1 < diff) {
			diff = size1;
		}
		
		for (int i = 0; i < diff; ++i) {
			list2.addFirst(list1.removeLast());
		}
	}
	
	/**
	 * ??̷̳???Ķ??λ???????
	 * @param result һ???̵߳ķ?????
	 * @param result2 ??һ???̵߳ķ?????
	 * @param seqs ??һ???̵߳ķ??????һ???̷߳???Ķ?Ӧ??ϵ
	 * @param ctx ??????????
	 * @return
	 */
	public void gather2(IArray result, IArray result2, int []seqs, Context ctx) {
		if (isRank) {
			Comparator comparator = this.comparator;
			for (int i = 1, len = result2.size(); i <= len; ++i) {
				if (seqs[i] != 0) {
					RankArray rankArray1 = (RankArray)result.get(seqs[i]);
					RankArray rankArray2 = (RankArray)result2.get(i);
					if (rankArray1 == null) {
						result.set(seqs[i], rankArray2);
					} else if (rankArray2 != null) {
						ObjectArray valueArray = rankArray2.getValueArray();
						for (int v = 1, vcount = valueArray.size(); v <= vcount; ++v) {
							rankArray1.add(valueArray.get(v), comparator);
						}
					}
				}
			}
		} else if (isSame) {
			if (getExp != null) {
				topAll(result, result2, seqs, ctx);
			} else if (isPositive) {
				minAll(result, result2, seqs);
			} else {
				maxAll(result, result2, seqs);
			}
		} else if (exp != null) {
			for (int i = 1, len = result2.size(); i <= len; ++i) {
				if (seqs[i] != 0) {
					MinHeap heap1 = (MinHeap)result.get(seqs[i]);
					MinHeap heap2 = (MinHeap)result2.get(i);
					if (heap1 == null) {
						result.set(seqs[i], heap2);
					} else if (heap2 != null) {
						heap1.insertAll(heap2);
					}
				}
			}
		} else {
			int count = this.count;
			if (isPositive) {
				for (int i = 1, len = result2.size(); i <= len; ++i) {
					if (seqs[i] != 0) {
						ArrayList list1 = (ArrayList)result.get(seqs[i]);
						ArrayList list2 = (ArrayList)result2.get(i);
						if (list1 == null) {
							result.set(seqs[i], list2);
						} else if (list2 != null) {
							addToArrayList(list1, list2, count);
						}
					}
				}
			} else {
				for (int i = 1, len = result2.size(); i <= len; ++i) {
					if (seqs[i] != 0) {
						LinkedList list1 = (LinkedList)result.get(seqs[i]);
						LinkedList list2 = (LinkedList)result2.get(i);
						if (list1 == null) {
							result.set(seqs[i], list2);
						} else if (list2 != null) {
							addToLinkedList(list1, list2, count);
							result.set(seqs[i], list2);
						}
					}
				}
			}
		}
	}
	private static void addToRankArray(RankArray array, Object obj, Comparator comparator) {
		if (obj != null) {
			array.add(obj, comparator);
		}
	}
	
	private static void addToRankArray(RankArray array, Object obj, 
			Expression exp, Context ctx, Comparator comparator) {
		ComputeStack stack = ctx.getComputeStack();
		try {
			if (obj instanceof Sequence) {
				Sequence tmpSeq = (Sequence)obj;
				Current current = new Current(tmpSeq);
				stack.push(current);
				
				for (int i = 1, len = tmpSeq.length(); i <= len; ++i) {
					current.setCurrent(i);
					Object val = exp.calculate(ctx);
					
					if (val != null) {
						Object []vals = new Object[2];
						vals[0] = exp.calculate(ctx);
						vals[1] = current.getCurrent();
						array.add(vals, comparator);
					}
				}
			} else if (obj instanceof BaseRecord) {
				stack.push((BaseRecord)obj);
				Object val = exp.calculate(ctx);
				
				if (val != null) {
					Object []vals = new Object[2];
					vals[0] = val;
					vals[1] = obj;
					array.add(vals, comparator);
				}
			} else if (obj != null) {
				MessageManager mm = EngineMessage.get();
				throw new RQException("top" + mm.getMessage("function.invalidParam"));
			}
		} finally {
			stack.pop();
		}
	}
}