package cz.brmlab.yodaqa.pipeline;

import org.apache.uima.UimaContext;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.cas.AbstractCas;
import org.apache.uima.cas.CASException;
import org.apache.uima.cas.FSIndex;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.fit.component.JCasMultiplier_ImplBase;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.util.Level;

import cz.brmlab.yodaqa.model.SearchResult.ResultInfo;
import cz.brmlab.yodaqa.model.CandidateAnswer.AnswerInfo;
import cz.brmlab.yodaqa.model.FinalAnswer.Answer;

/**
 * Take a set of per-answer CAS and merge them to a final result CAS.
 *
 * So far, this answer ranker is super-primitive, just to showcase
 * a merging CAS multiplier behavior. But it actually does the job. */

public class AnswerRanker extends JCasMultiplier_ImplBase {
	JCas finalCas;
	boolean isLast;

	public void initialize(UimaContext aContext) throws ResourceInitializationException {
		super.initialize(aContext);
		isLast = false;
	}

	public void process(JCas candCas) throws AnalysisEngineProcessException {
		if (finalCas == null)
			finalCas = getEmptyJCas();

		Answer answer = new Answer(finalCas);
		answer.setText(candCas.getDocumentText());

		AnswerInfo ai;
		ResultInfo ri;
		FSIterator infos;

		ai = (AnswerInfo) candCas.getJFSIndexRepository().getAllIndexedFS(AnswerInfo.type).next();
		ri = (ResultInfo) candCas.getJFSIndexRepository().getAllIndexedFS(ResultInfo.type).next();

		answer.setConfidence(ai.getConfidence() * ri.getRelevance());
		isLast = ai.getIsLast() && ri.getIsLast();

		// System.err.println("AR process: " + answer.getText() + " c " + answer.getConfidence());

		answer.addToIndexes();
	}

	public boolean hasNext() throws AnalysisEngineProcessException {
		return isLast;
	}

	public AbstractCas next() throws AnalysisEngineProcessException {
		if (!isLast)
			throw new AnalysisEngineProcessException();

		JCas outputCas = finalCas;
		finalCas = null;
		isLast = false;
		return outputCas;
	}
}

@@ -29,16 +29,145 @@
 eline;%0A%0A
+import java.util.HashMap;%0Aimport java.util.LinkedList;%0Aimport java.util.List;%0Aimport java.util.Map;%0Aimport java.util.Map.Entry;%0A%0A
 import o
@@ -993,16 +993,68 @@
 the job.
+%0A * It also deduplicates answers with the same text.
  */%0A%0Apub
@@ -1110,16 +1110,58 @@
 lBase %7B%0A
+%09Map%3CString, List%3CAnswer%3E%3E answersByText;%0A
 %09JCas fi
@@ -1303,16 +1303,71 @@
 ntext);%0A
+%09%09answersByText = new HashMap%3CString, List%3CAnswer%3E%3E();%0A
 %09%09isLast
@@ -1556,23 +1556,22 @@
 ;%0A%09%09
-answer.setText(
+String text = 
 cand
@@ -1591,16 +1591,39 @@
 ntText()
+;%0A%09%09answer.setText(text
 );%0A%0A%09%09An
@@ -2070,28 +2070,181 @@
 %0A%0A%09%09
-answer.addToIndexes(
+List%3CAnswer%3E answers = answersByText.get(text);%0A%09%09if (answers == null) %7B%0A%09%09%09answers = new LinkedList%3CAnswer%3E();%0A%09%09%09answersByText.put(text, answers);%0A%09%09%7D%0A%09%09answers.add(answer
 );%0A%09
@@ -2463,16 +2463,553 @@
 ion();%0A%0A
+%09%09/* Deduplicate Answer objects and index them. */%0A%09%09for (Entry%3CString, List%3CAnswer%3E%3E entry : answersByText.entrySet()) %7B%0A%09%09%09Answer mainAns = null;%0A%09%09%09for (Answer answer : entry.getValue()) %7B%0A%09%09%09%09if (mainAns == null) %7B%0A%09%09%09%09%09mainAns = answer;%0A%09%09%09%09%09continue;%0A%09%09%09%09%7D%0A%09%09%09%09System.err.println(%22final merging %22 + mainAns.getText() + %22%7C%22 + answer.getText()%0A%09%09%09%09%09%09+ %22 :: %22 + mainAns.getConfidence() + %22, %22 + answer.getConfidence());%0A%09%09%09%09mainAns.setConfidence(mainAns.getConfidence() + answer.getConfidence());%0A%09%09%09%7D%0A%09%09%09mainAns.addToIndexes();%0A%09%09%7D%0A%0A
 %09%09JCas o
@@ -3048,16 +3048,40 @@
 = null;%0A
+%09%09answersByText = null;%0A
 %09%09isLast

Deduplicate finally produced Answers