package cz.brmlab.yodaqa.analysis.question;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.uima.UimaContext;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.fit.component.JCasAnnotator_ImplBase;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.ResourceInitializationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cz.brmlab.yodaqa.model.Question.Clue;

/**
 * Merge Clues whose coveredText is the same.
 *
 * The redundant annotations will be removed; the one with the highest score
 * will be kept; therefore, the resulting Clue score will be a maximum, not
 * a sum!
 *
 * When merging CandidateAnswers, independent production of each of them
 * is an additional evidence for the eventual answer, so we sum the scores.
 * But when merging Clues, they all stem from the base word and it was just
 * matched multiple ways, but these do not represent independent knowledge
 * sources, so we just do a max. */

public class CluesMergeByText extends JCasAnnotator_ImplBase {
	final Logger logger = LoggerFactory.getLogger(CluesMergeByText.class);

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

	public void process(JCas resultView) throws AnalysisEngineProcessException {
		Map<String, List<Clue>> cluesByText = new HashMap<String, List<Clue>>();

		/* Put all Clues in a text-addressed map. */
		for (Clue clue : JCasUtil.select(resultView, Clue.class)) {
			String text = clue.getCoveredText();
			List<Clue> clues = cluesByText.get(text);
			if (clues == null) {
				clues = new LinkedList<Clue>();
				cluesByText.put(text, clues);
			}
			clues.add(clue);
		}

		/* Deal with map items that hold multiple answers. */
		for (Entry<String, List<Clue>> entry : cluesByText.entrySet()) {
			if (entry.getValue().size() == 1)
				continue;

			Clue mainClue = null;
			for (Clue clue : entry.getValue()) {
				clue.removeFromIndexes();
				if (mainClue == null) {
					mainClue = clue;
				} else if (mainClue.getWeight() <= clue.getWeight()) {
					logger.debug("subduing " + mainClue.getCoveredText() + "|" + clue.getCoveredText()
							+ " :: " + mainClue.getWeight() + ", " + clue.getWeight());
					mainClue = clue;
				} else {
					logger.debug("subduing " + clue.getCoveredText() + "|" + mainClue.getCoveredText()
							+ " :: " + clue.getWeight() + ", " + mainClue.getWeight());
				}
			}
			mainClue.addToIndexes();
		}
	}
}

@@ -2253,229 +2253,269 @@
 %09%09%09%09
-logger.debug(%22subduing %22 + mainClue.getCoveredText() + %22%7C%22 + clue.getCoveredText()%0A%09%09%09%09%09%09%09+ %22 :: %22 + mainClue.getWeight() + %22, %22 + clue.getWeight());%0A%09%09%09%09%09mainClue = clue;%0A%09%09%09%09%7D else %7B%0A%09%09%09%09%09logger.debug(%22subduing %22 + cl
+subdueInfo(mainClue, clue);%0A%09%09%09%09%09mainClue = clue;%0A%09%09%09%09%7D else %7B%0A%09%09%09%09%09subdueInfo(clue, mainClue);%0A%09%09%09%09%7D%0A%09%09%09%7D%0A%09%09%09mainClue.addToIndexes();%0A%09%09%7D%0A%09%7D%0A%0A%09protected void subdueInfo(Clue subdued, Clue subduing) %7B%0A%09%09logger.debug(%22subduing %7B%7D(%7B%7D:%7B%7D) %3C%7C %7B%7D(%7B%7D:%7B%7D)%22,%0A%09%09%09subd
 ue
+d
 .get
@@ -2531,65 +2531,57 @@
 xt()
- + %22%7C%22 + mainCl
+,%0A%09%09%09subd
 ue
+d
 .get
-CoveredText
+Type().getShortName
 ()
+,
 %0A%09%09%09
-%09%09%09%09+ %22 :: %22 + cl
+subd
 ue
+d
 .get
@@ -2592,83 +2592,103 @@
 ht()
- + %22, %22 + mainClue.getWeight());
+,%0A%09%09%09subduing.getCoveredText(),
 %0A%09%09%09
-%09%7D%0A%09%09%09%7D%0A%09%09%09mainClue.addToIndexes();%0A%09%09%7D
+subduing.getType().getShortName(),%0A%09%09%09subduing.getWeight());
 %0A%09%7D%0A

Improve debug print with clue type info