@Override @SuppressWarnings({"unchecked"}) public void finished(Evaluation evaluation) { LongTreeMap.Entry<EvaluationInfo> entry = evaluations.getEntry(evaluation.order); assert entry.value.eval == evaluation; if (evaluation instanceof PredicateEvaluation) { PredicateEvaluation predicateEvaluation = (PredicateEvaluation) evaluation; if (predicateEvaluation.result != null) { if (predicateEvaluation.result instanceof Evaluation) { entry.value.eval = (Evaluation) predicateEvaluation.result; entry.value.eval.addListener(this); return; } else { entry.value.setResult(predicateEvaluation.result); entry.value.eval = null; pendingCount--; } } else { entry.value.doDiscards(); evaluations.deleteEntry(entry); if (entry.value.eval != null) pendingCount--; } } else { entry.value.setResult(evaluation.getResult()); entry.value.eval = null; pendingCount--; } tryToFinish(); }
private void fireInstantResult(LongTreeMap<Object> result) { LongTreeMap.Entry<Object> entry = result.firstEntry(); while (entry != null) { if (entry.value instanceof NodeItem) { event.onInstantResult(expression, (NodeItem) entry.value); entry.value = Event.DUMMY_VALUE; } entry = entry.next(); } result.clear(); // to avoid memory leak }
@Override public void discard(long order) { LongTreeMap.Entry<EvaluationInfo> entry = evaluations.getEntry(order); if (entry != null) { if (entry.value.discard() == 0) { evaluations.deleteEntry(entry); if (entry.value.eval != null) { pendingCount--; entry.value.eval.removeListener(this); } } } }
private void consumedResult() { int resultSize = result.size(); if (resultSize > 0 && !expression.many) { if (resultSize > 1) result.deleteEntry(result.lastEntry()); if (expression.first) { if (pendingEvaluationHead == null || result.firstEntry().getKey() <= pendingEvaluationHead.order) resultPrepared(); else if (!expired) { manuallyExpired = true; expired = true; } } else resultPrepared(); } else if (expired && pendingEvaluationHead == null) resultPrepared(); }
@SuppressWarnings({"unchecked"}) public Object computeResult() { if (expression.forEach) { List<Object> result = new ArrayList<Object>(evaluations.size()); for (LongTreeMap.Entry entry = evaluations.firstEntry(); entry != null; entry = entry.next()) result.add(computeResultItem(((EvaluationInfo) entry.value).result)); return result; } else { LongTreeMap result = new LongTreeMap(); for (LongTreeMap.Entry<EvaluationInfo> entry = evaluations.firstEntry(); entry != null; entry = entry.next()) result.putAll(entry.value.result); return computeResultItem(result); } }
private void consumeChildEvaluation(LongTreeMap<Object> childResult) { boolean prepareResult = false; int size = childResult.size(); if (size == 1 && expression.resultType == DataType.NUMBER) { Object resultItem = childResult.firstEntry().value; if (resultItem instanceof Double && ((Double) resultItem).isNaN()) { result.clear(); prepareResult = true; } } if (size > 0) { if (predicateChain == 0) fireInstantResult(childResult); if (result.size() > 0) { if (nodeSetListener != null) { for (LongTreeMap.Entry<Object> entry = childResult.firstEntry(); entry != null; entry = entry.next()) { if (result.put(entry.getKey(), entry.value) != null) nodeSetListener.discard(entry.getKey()); } } else result.putAll(childResult); } else result = childResult; } consumedResult(); if (prepareResult) resultPrepared(); }
private void consumeChildEvaluation(long order, Object resultItem) { boolean prepareResult = false; if (expression.resultType == DataType.NUMBER) { if (resultItem instanceof Double && ((Double) resultItem).isNaN()) { result.clear(); prepareResult = true; } } if (predicateChain == 0) { event.onInstantResult(expression, (NodeItem) resultItem); resultItem = Event.DUMMY_VALUE; } result.put(order, resultItem); consumedResult(); if (prepareResult) resultPrepared(); }
private int pendingCount() { int count = 0; for (LongTreeMap.Entry<EvaluationInfo> entry = evaluations.firstEntry(); entry != null; entry = entry.next()) { if (entry.value.eval != null) count++; } return count; }
@Override public void finished() { contextsPending--; if (contextsPending == 0) { if (expression.union.hitExpression != null) { for (EvaluationInfo evalInfo : new ArrayList<EvaluationInfo>(evaluations.values())) evalInfo.doFinish(); if (positionTracker != null) positionTracker.expired(); } } tryToFinish(); }
private void consume(Event event) { assert lastStep; Object resultItem = expression.getResultItem(event); if (resultItem instanceof Evaluation) { Evaluation eval = (Evaluation) resultItem; stringEvaluations.add(eval); eval.addListener(this); eval.start(); } else if (predicateChain == 0) { event.onInstantResult(expression, (NodeItem) resultItem); resultItem = Event.DUMMY_VALUE; } assert resultItem != null : "ResultItem should be non-null"; result.put(event.order(), resultItem); consumedResult(); if (nodeSetListener != null) nodeSetListener.mayHit(); }
@SuppressWarnings({"unchecked", "UnnecessaryBoxing"}) private Object computeResultItem(LongTreeMap result) { switch (expression.resultType) { case NODESET: case STRINGS: case NUMBERS: return new ArrayList(result.values()); case NUMBER: if (expression.relativeExpression instanceof Count) return new Double(result.size()); else { double d = 0; for (LongTreeMap.Entry entry = result.firstEntry(); entry != null; entry = entry.next()) d += (Double) entry.value; return d; } case BOOLEAN: return !result.isEmpty(); default: if (result.isEmpty()) return expression.resultType.defaultValue; else return result.firstEntry().value; } }
@Override public final void finished(Evaluation evaluation) { assert !finished : "can't consume evaluation result after finish"; if (evaluation == predicateEvaluation) { predicateResult = (Boolean) evaluation.getResult(); assert predicateResult != null : "evaluation result should be non-null"; if (predicateResult == Boolean.FALSE) { if (nodeSetListener != null) { for (LongTreeMap.Entry<Object> entry = result.firstEntry(); entry != null; entry = entry.next()) nodeSetListener.discard(entry.getKey()); } result.clear(); if (stringEvaluations != null) { for (Evaluation stringEval : stringEvaluations) stringEval.removeListener(this); stringEvaluations = null; } resultPrepared(); } else { if (predicateChain != -1) decreasePredicateChain(); if (resultPrepared) finished(); } } else if (evaluation instanceof PredicateEvaluation) { PredicateEvaluation predicateEvaluation = (PredicateEvaluation) evaluation; remove(predicateEvaluation); if (predicateEvaluation.result != null) { Object resultItem = predicateEvaluation.result; if (resultItem instanceof Evaluation) { Evaluation stringEval = (Evaluation) resultItem; stringEvaluations.add(stringEval); stringEval.addListener(this); } consumeChildEvaluation(predicateEvaluation.order, resultItem); } else { if (nodeSetListener != null) nodeSetListener.discard(predicateEvaluation.order); consumedResult(); } } else if (evaluation instanceof LocationEvaluation) { LocationEvaluation locEval = (LocationEvaluation) evaluation; remove(locEval); if (locEval.stringEvaluations != null) { for (Evaluation stringEval : locEval.stringEvaluations) stringEval.addListener(this); stringEvaluations.addAll(locEval.stringEvaluations); } boolean wasExpired = expired; consumeChildEvaluation(locEval.result); if (!wasExpired && expired) { assert !finished; LinkableEvaluation eval = locEval.next; while (eval != null) { eval.removeListener(this); remove(eval); eval = eval.next; } if (pendingEvaluationHead == null) resultPrepared(); } } else { stringEvaluations.remove(evaluation); consumeChildEvaluation(evaluation.order, evaluation.getResult()); } }
@Override public void mayHit() { long order = event.order(); EvaluationInfo evalInfo = evaluations.get(order); if (evalInfo == null) { evaluations.put( order, evalInfo = new EvaluationInfo(event, expression.union.hitExpression, order, nodeSetListener)); if (positionTracker != null) { event.positionTrackerStack.addFirst(positionTracker); positionTracker.addEvaluation(event); } Expression predicate = expression.union.predicateSet.getPredicate(); Object predicateResult = predicate == null ? Boolean.TRUE : event.evaluate(predicate); if (predicateResult == Boolean.TRUE) { Object r = event.evaluate(expression.relativeExpression); if (r == null) { event.evaluation.addListener(this); event.evaluation.start(); evalInfo.eval = event.evaluation; pendingCount++; if (nodeSetListener != null) { if (event.evaluation instanceof LocationEvaluation) ((LocationEvaluation) event.evaluation).nodeSetListener = evalInfo; else ((PathEvaluation) event.evaluation).nodeSetListener = evalInfo; } } else { if (nodeSetListener != null) nodeSetListener.mayHit(); evalInfo.setResult(r); } } else if (predicateResult == null) { Evaluation predicateEvaluation = event.evaluation; Object resultItem = expression.relativeExpression.getResult(event); if (nodeSetListener != null && !(nodeSetListener instanceof Event)) { // nodeSetListener will be event if xmlBuilder is set if (resultItem instanceof LocationEvaluation) ((LocationEvaluation) resultItem).nodeSetListener = evalInfo; else ((PathEvaluation) resultItem).nodeSetListener = evalInfo; } Evaluation childEval = new PredicateEvaluation( expression.relativeExpression, event.order(), resultItem, event, predicate, predicateEvaluation); childEval.addListener(this); childEval.start(); evalInfo.eval = childEval; pendingCount++; } else throw new ImpossibleException(); } evalInfo.hitCount++; if (evalInfo.hitCount == 1 && positionTracker != null) { positionTracker.startEvaluation(); event.positionTrackerStack.pollFirst(); } }