/** @should return person data for each obs in the passed context */
  @Override
  public EvaluatedObsData evaluate(ObsDataDefinition definition, EvaluationContext context)
      throws EvaluationException {

    EvaluatedObsData c = new EvaluatedObsData(definition, context);

    // create a map of obs ids -> patient ids

    HqlQueryBuilder q = new HqlQueryBuilder();
    q.select("o.obsId", "o.personId");
    q.from(Obs.class, "o");
    q.whereObsIn("o.obsId", context);

    Map<Integer, Integer> convertedIds =
        evaluationService.evaluateToMap(q, Integer.class, Integer.class, context);

    if (!convertedIds.keySet().isEmpty()) {
      // create a new (person) evaluation context using the retrieved ids
      PersonEvaluationContext personEvaluationContext = new PersonEvaluationContext();
      personEvaluationContext.setBasePersons(
          new PersonIdSet(new HashSet<Integer>(convertedIds.values())));

      // evaluate the joined definition via this person context
      PersonToObsDataDefinition def = (PersonToObsDataDefinition) definition;
      EvaluatedPersonData pd =
          Context.getService(PersonDataService.class)
              .evaluate(def.getJoinedDefinition(), personEvaluationContext);

      // now create the result set by mapping the results in the person data set to obs ids
      for (Integer obsId : convertedIds.keySet()) {
        c.addData(obsId, pd.getData().get(convertedIds.get(obsId)));
      }
    }
    return c;
  }
  /**
   * @see PersonDataEvaluator#evaluate(PersonDataDefinition, EvaluationContext)
   * @should return the most preferred name for each person in the passed context
   * @should return empty result set for an empty base cohort
   * @should return the preferred name for all persons
   */
  public EvaluatedPersonData evaluate(PersonDataDefinition definition, EvaluationContext context)
      throws EvaluationException {
    EvaluatedPersonData c = new EvaluatedPersonData(definition, context);

    if (context.getBaseCohort() != null && context.getBaseCohort().isEmpty()) {
      return c;
    }

    HqlQueryBuilder q = new HqlQueryBuilder();
    q.select("pn.person.personId", "pn");
    q.from(PersonName.class, "pn");
    q.wherePersonIn("pn.person.personId", context);
    q.orderAsc("pn.preferred");

    Map<Integer, Object> data = evaluationService.evaluateToMap(q, Integer.class, Object.class);
    c.setData(data);

    return c;
  }