package org.openmrs.module.reporting.data.obs.evaluator;
import org.openmrs.Obs;
import org.openmrs.annotation.Handler;
import org.openmrs.api.context.Context;
import org.openmrs.module.reporting.data.obs.EvaluatedObsData;
import org.openmrs.module.reporting.data.obs.definition.ObsDataDefinition;
import org.openmrs.module.reporting.data.obs.definition.PersonToObsDataDefinition;
import org.openmrs.module.reporting.data.person.EvaluatedPersonData;
import org.openmrs.module.reporting.data.person.service.PersonDataService;
import org.openmrs.module.reporting.evaluation.EvaluationContext;
import org.openmrs.module.reporting.evaluation.EvaluationException;
import org.openmrs.module.reporting.evaluation.context.ObsEvaluationContext;
import org.openmrs.module.reporting.evaluation.context.PersonEvaluationContext;
import org.openmrs.module.reporting.evaluation.querybuilder.HqlQueryBuilder;
import org.openmrs.module.reporting.evaluation.service.EvaluationService;
import org.openmrs.module.reporting.query.person.PersonIdSet;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashSet;
import java.util.Map;
/**
* Evaluates a PersonToObsDataDefinition to produce a ObsData
*/
@Handler(supports=PersonToObsDataDefinition.class, order=50)
public class PersonToObsDataEvaluator implements ObsDataEvaluator {
@Autowired
EvaluationService evaluationService;
/**
* @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;
}
}