package org.openmrs.module.reporting.web.controller; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openmrs.module.htmlwidgets.web.WidgetUtil; import org.openmrs.module.reporting.common.ObjectUtil; import org.openmrs.module.reporting.common.ReflectionUtil; import org.openmrs.module.reporting.definition.DefinitionContext; import org.openmrs.module.reporting.definition.DefinitionUtil; import org.openmrs.module.reporting.definition.configuration.Property; import org.openmrs.module.reporting.evaluation.Definition; import org.openmrs.module.reporting.evaluation.parameter.Parameter; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class EditAnnotatedDefinitionController { protected static Log log = LogFactory.getLog(EditAnnotatedDefinitionController.class); @ModelAttribute("definition") public Definition getDefinition(@RequestParam(required = false, value = "uuid") String uuid, @RequestParam(required = false, value = "type") Class<? extends Definition> type) { Definition d = null; if (ObjectUtil.notNull(uuid)) { d = DefinitionContext.getDefinitionByUuid(type, uuid); } if (d == null) { try { d = type.newInstance(); } catch (Exception e) { throw new IllegalArgumentException("Unable to create definition instance of type " + type); } } return d; } /** * Basically acts as the formBackingObject() method for saving a CohortDefinition. */ @RequestMapping("/module/reporting/definition/editAnnotatedDefinition") public String editAnnotatedDefinition(ModelMap model, @RequestParam(required = true, value = "parentType") Class<? extends Definition> parentType, @ModelAttribute("definition") Definition definition) { model.addAttribute("parentType", parentType); addPropertiesToModel(model, definition); return "/module/reporting/definition/editAnnotatedDefinition"; } /** * Saves a cohort definition. */ @RequestMapping("/module/reporting/definition/saveAnnotatedDefinition") @SuppressWarnings({"unchecked", "rawtypes"}) public String saveAnnotatedDefinition(@RequestParam(required = true, value = "parentType") Class<? extends Definition> parentType, @ModelAttribute("definition") Definition definition, BindingResult bindingResult, ModelMap model, HttpServletRequest request) { definition.getParameters().clear(); for (Property p : DefinitionUtil.getConfigurationProperties(definition)) { String fieldName = p.getField().getName(); String prefix = "parameter." + fieldName; String valParamName = prefix + ".value"; boolean isParameter = "t".equals(request.getParameter(prefix + ".allowAtEvaluation")); try { Object valToSet = WidgetUtil.getFromRequest(request, valParamName, p.getField()); Class<? extends Collection<?>> collectionType = null; Class<?> fieldType = p.getField().getType(); if (ReflectionUtil.isCollection(p.getField())) { collectionType = (Class<? extends Collection<?>>) p.getField().getType(); fieldType = (Class<?>) ReflectionUtil.getGenericTypes(p.getField())[0]; } if (isParameter) { //skip primitive types since they already have a default value if (!fieldType.isPrimitive()) { ReflectionUtil.setPropertyValue(definition, p.getField(), null); } else { //use the wrapper class type equivalent so that the WidgetTag doesn't fail fieldType = ReflectionUtil.getWrapperMap().get(fieldType.getName()); } String paramLabel = ObjectUtil.nvlStr(request.getParameter(prefix + ".label"), fieldName); Properties widgetConfig = (Properties)WidgetUtil.getFromRequest(request, prefix+".widgetConfiguration", Properties.class, (Class)null); Parameter param = new Parameter(fieldName, paramLabel, fieldType, collectionType, valToSet, widgetConfig); definition.addParameter(param); } else { ReflectionUtil.setPropertyValue(definition, p.getField(), valToSet); } } catch (NumberFormatException e) { bindingResult.rejectValue(fieldName, "reporting.error.invalidNumber", "Only integers are allowed"); } } // TODO: Add additional validation in if (bindingResult.hasErrors()) { addPropertiesToModel(model, definition); model.addAttribute("errors", bindingResult); return "/module/reporting/definition/editAnnotatedDefinition"; } if ("".equals(definition.getUuid())) { definition.setUuid(null); } log.warn("Saving: " + definition); DefinitionContext.saveDefinition(definition); return "redirect:/module/reporting/definition/manageDefinitions.form?type=" + parentType.getName(); } private void addPropertiesToModel(ModelMap model, Definition definition) { List<Property> properties = DefinitionUtil.getConfigurationProperties(definition); model.addAttribute("configurationProperties", properties); Map<String, List<Property>> groups = new LinkedHashMap<String, List<Property>>(); for (Property p : properties) { List<Property> l = groups.get(p.getGroup()); if (l == null) { l = new ArrayList<Property>(); groups.put(p.getGroup(), l); } l.add(p); } model.addAttribute("groupedProperties", groups); } }