private void pushAnswerToTop(Answer topAnswer, List<Answer> answers) {
    // See if the top answer is already in the answer list. If it is, remove it
    Iterator<Answer> iter = answers.iterator();
    while (iter.hasNext()) {
      if (iter.next().getClassName().equals(topAnswer.getClassName())) {
        iter.remove();
      }
    }

    // Set this top answer as HIGH with 100% confidence
    topAnswer.setConfidence(1.00);
    topAnswer.setConfidenceCategory(ConfidenceCategoryEnum.HIGH);

    // Add this answer to the top
    answers.add(0, topAnswer);
  }
  @Override
  public Response askQuestion(String conversationId, MessageRequest message)
      throws NotFoundException {
    logger.entry(message.getMessage());

    if (message.getReferrer() != null) {
      if (message.getReferrer().getSource() == SourceEnum.REFINEMENT
          && message.getReferrer().getMessageId() == null) {
        return getBadRequestResponse(
            "messageId required when referrer source is " + SourceEnum.REFINEMENT);
      }
      if (message.getReferrer().getSource() == null) {
        return getBadRequestResponse("referrer source required when referrer is set");
      }
    }

    if (message.getMessage().length() > MAX_QUESTION_LENGTH) {
      return getBadRequestResponse(
          MessageKey.AQWQAC14004E_question_too_long_1.getMessage(message.getMessage())
              .getFormattedMessage());
    }

    if (service == null) {
      return error(MessageKey.AQWQAC14001E_error_selection_correct_classifier.getMessage());
    }

    List<NLClassifier> classifiers = service.getClassifiers();
    if (classifiers.isEmpty()) {
      return error(MessageKey.AQWQAC14002E_no_classifier_instances.getMessage());
    }

    NLClassifier classifier = null;
    for (NLClassifier potentialClassifier : classifiers) {
      if (potentialClassifier.getStatus().equals(Status.AVAILABLE)) {
        classifier = potentialClassifier;
        break;
      }
    }

    if (classifier == null) {
      return error(MessageKey.AQWQAC14003E_no_available_classifiers.getMessage());
    }

    NLClassiferClassifyResponse classifyResponse = classifier.classify(message.getMessage());

    List<Answer> answers = new ArrayList<Answer>();
    for (NLClassifiedClass classifiedClass : classifyResponse.getClasses()) {
      try {
        answers.add(resolver.resolve(classifiedClass));
      } catch (ResolutionException e) {
        logger.warn(MessageKey.AQWQAC12100W_could_not_resolve_answer_1.getMessage(e.getMessage()));
      }
    }

    List<Answer> previousAnswers = responseCache.get(conversationId);
    responseCache.put(conversationId, answers);

    // If there was no referrer, or if it's a top question, cache this response
    if (message.getReferrer() != null) {
      Answer knownAnswer = null;
      // This is either a refinement question (did you mean) or a top question, so force the correct
      // answer to the top
      if (message.getReferrer().getSource() == SourceEnum.TOP_QUESTION) {
        try {
          knownAnswer = topQuestionsStore.getAnswer(message.getMessage());
        } catch (QuestionNotFoundException | ResolutionException e) {
          logger.warn(MessageKey.AQWQAC12003W_question_not_in_top_question_store.getMessage(), e);
        }
      }
      if (message.getReferrer().getSource() == SourceEnum.REFINEMENT) {
        if (previousAnswers.size() > 0) {
          // Find the refinement question in our previously cached list
          for (Answer previousAnswer : previousAnswers) {
            if (previousAnswer.getCanonicalQuestion().equals(message.getMessage())) {
              knownAnswer = previousAnswer;
              break;
            }
          }
        }
        if (knownAnswer == null) {
          logger.warn(
              MessageKey.AQWQAC12004W_question_not_in_response_cache_1.getMessage(
                  message.getMessage()));
        }
      }
      if (knownAnswer != null) {
        pushAnswerToTop(knownAnswer, answers);
      }
    }

    if (answers.size() > 0) {
      answers = categorizer.categorize(answers);
    }

    String previousMessageId = null;
    if (message.getReferrer() != null) {
      // This is a refinement/suggestion to a high confidence incorrect or low confidence answer.
      // Keep track of the question/response that got us here.
      previousMessageId = message.getReferrer().getMessageId();
    }

    InputMode mode = message.getReferrer() == null ? InputMode.TYPED : InputMode.CLICKED;
    String messageId =
        tracking.questionAsked(
            conversationId, previousMessageId, message.getMessage(), mode, answers);

    return getOkResponse(new MessageResponse(messageId, message.getMessage(), answers));
  }