package org.openmrs.module.reporting.web.controller;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.module.reporting.cohort.definition.CohortDefinition;
import org.openmrs.module.reporting.common.MessageUtil;
import org.openmrs.module.reporting.common.ObjectUtil;
import org.openmrs.module.reporting.data.DataDefinition;
import org.openmrs.module.reporting.data.encounter.definition.EncounterDataDefinition;
import org.openmrs.module.reporting.data.encounter.definition.PatientToEncounterDataDefinition;
import org.openmrs.module.reporting.data.encounter.definition.PersonToEncounterDataDefinition;
import org.openmrs.module.reporting.data.patient.definition.PatientDataDefinition;
import org.openmrs.module.reporting.data.patient.definition.PatientDataSetDataDefinition;
import org.openmrs.module.reporting.data.patient.definition.PersonToPatientDataDefinition;
import org.openmrs.module.reporting.data.person.definition.AgeAtDateOfOtherDataDefinition;
import org.openmrs.module.reporting.data.person.definition.PersonDataDefinition;
import org.openmrs.module.reporting.dataset.definition.CohortIndicatorDataSetDefinition;
import org.openmrs.module.reporting.dataset.definition.EncounterDataSetDefinition;
import org.openmrs.module.reporting.dataset.definition.MultiPeriodIndicatorDataSetDefinition;
import org.openmrs.module.reporting.definition.DefinitionContext;
import org.openmrs.module.reporting.evaluation.Definition;
import org.openmrs.module.reporting.query.Query;
import org.openmrs.module.reporting.query.encounter.definition.EncounterQuery;
import org.openmrs.module.reporting.query.person.definition.PersonQuery;
import org.openmrs.module.reporting.web.controller.mapping.DefinitionMappingHandler;
import org.openmrs.util.HandlerUtil;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class ManageDefinitionsController {
protected static Log log = LogFactory.getLog(ManageDefinitionsController.class);
/**
* Manage Definitions Controller
*/
@RequestMapping("/module/reporting/definition/manageDefinitions")
public void manageDefinitions(
@RequestParam(required=true, value="type") Class<? extends Definition> type,
@RequestParam(required=false, value="includeRetired") Boolean includeRetired,
ModelMap model) {
List<Class<? extends Definition>> allTypes = new ArrayList<Class<? extends Definition>>();
if (DataDefinition.class.isAssignableFrom(type)) {
allTypes.add(PersonDataDefinition.class);
allTypes.add(PatientDataDefinition.class);
allTypes.add(EncounterDataDefinition.class);
}
else if (Query.class.isAssignableFrom(type)) {
allTypes.add(PersonQuery.class);
allTypes.add(CohortDefinition.class);
allTypes.add(EncounterQuery.class);
//allTypes.add(ObsQuery.class); TODO: None of these are implemented yet
}
model.addAttribute("allTypes", allTypes);
List<Class<? extends Definition>> hiddenDefinitions = new ArrayList<Class<? extends Definition>>();
hiddenDefinitions.add(CohortIndicatorDataSetDefinition.class);
hiddenDefinitions.add(MultiPeriodIndicatorDataSetDefinition.class);
hiddenDefinitions.add(EncounterDataSetDefinition.class);
hiddenDefinitions.add(PatientDataSetDataDefinition.class);
hiddenDefinitions.add(AgeAtDateOfOtherDataDefinition.class);
hiddenDefinitions.add(PersonToPatientDataDefinition.class);
hiddenDefinitions.add(PersonToEncounterDataDefinition.class);
hiddenDefinitions.add(PatientToEncounterDataDefinition.class);
model.addAttribute("hiddenDefinitions", hiddenDefinitions);
// Get all Definitions
boolean retired = includeRetired != null && includeRetired.booleanValue();
List<? extends Definition> definitions = DefinitionContext.getAllDefinitions(type, retired);
// Construct a Map of Definition Type to List of Definitions
Map<Class<? extends Definition>, List<Definition>> defsByType =
new TreeMap<Class<? extends Definition>, List<Definition>>(new DefinitionNameComparator());
// Initialize the Map with all known supported types
for (Class<? extends Definition> supportedType : DefinitionContext.getDefinitionService(type).getDefinitionTypes()) {
if (!hiddenDefinitions.contains(supportedType)) {
defsByType.put(supportedType, new ArrayList<Definition>());
}
}
// Add all saved Definitions to the Map
for (Definition d : definitions) {
List<Definition> l = defsByType.get(d.getClass());
if (l != null) {
l.add(d);
}
}
model.addAttribute("type", type);
model.addAttribute("definitions", defsByType);
model.addAttribute("allDefinitions", definitions);
}
/**
* Edit Definition Controller
*/
@RequestMapping("/module/reporting/definition/editDefinition")
public String editDefinition(
@RequestParam(required=true, value="type") Class<? extends Definition> type,
@RequestParam(required=false, value="uuid") String uuid,
ModelMap model) {
DefinitionMappingHandler handler = HandlerUtil.getPreferredHandler(DefinitionMappingHandler.class, type);
if (ObjectUtil.isNull(uuid)) {
return "redirect:" + handler.getCreateUrl(type);
}
else {
Definition d = DefinitionContext.getDefinitionService(type).getDefinitionByUuid(uuid);
return "redirect:" + handler.getEditUrl(d);
}
}
/**
* Purge Definition Controller
*/
@RequestMapping("/module/reporting/definition/purgeDefinition")
public String purgeDefinition(
@RequestParam(required=true, value="type") Class<? extends Definition> type,
@RequestParam(required=true, value="uuid") String uuid,
ModelMap model) {
DefinitionContext.purgeDefinition(type, uuid);
return "redirect:manageDefinitions.form?type="+type.getName();
}
/**
* Retire Definition Controller
*/
@RequestMapping("/module/reporting/definition/retireDefinition")
public String retireDefinition(
@RequestParam(required=true, value="type") Class<? extends Definition> type,
@RequestParam(required=true, value="uuid") String uuid,
ModelMap model) {
Definition d = DefinitionContext.getDefinitionService(type).getDefinitionByUuid(uuid);
DefinitionContext.retireDefinition(d);
return "redirect:manageDefinitions.form?type="+type.getName();
}
/**
* Retire Definition Controller
*/
@RequestMapping("/module/reporting/definition/unretireDefinition")
public String unretireDefinition(
@RequestParam(required=true, value="type") Class<? extends Definition> type,
@RequestParam(required=true, value="uuid") String uuid,
ModelMap model) {
Definition d = DefinitionContext.getDefinitionService(type).getDefinitionByUuid(uuid);
DefinitionContext.unretireDefinition(d);
return "redirect:manageDefinitions.form?type="+type.getName();
}
/**
* Comparator which orders Definitions based on their Display Label
*/
public class DefinitionNameComparator implements Comparator<Class<? extends Definition>> {
/**
* @see Comparator#compare(Object, Object)
*/
public int compare(Class<? extends Definition> o1, Class<? extends Definition> o2) {
String key1 = MessageUtil.getDisplayLabel(o1);
String key2 = MessageUtil.getDisplayLabel(o2);
return key1.compareTo(key2);
}
}
}