Java tutorial
/** * This Source Code Form is subject to the terms of the Mozilla Public License, * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. * * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS * graphic logo is a trademark of OpenMRS Inc. */ package org.openmrs.module.radiology.web.controller; import java.io.IOException; import java.io.InputStream; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openmrs.Obs; import org.openmrs.api.ObsService; import org.openmrs.api.context.Context; import org.openmrs.module.radiology.RadiologyOrder; import org.openmrs.module.radiology.RadiologyProperties; import org.openmrs.module.radiology.RadiologyService; import org.openmrs.module.radiology.Study; import org.openmrs.obs.ComplexData; import org.openmrs.propertyeditor.ObsEditor; import org.openmrs.validator.ObsValidator; import org.openmrs.web.WebConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.servlet.ModelAndView; @Controller @RequestMapping(value = "/module/radiology/radiologyObs.form") public class RadiologyObsFormController { Log log = LogFactory.getLog(getClass()); private static final String RADIOLOGY_OBS_FORM_PATH = "module/radiology/radiologyObsForm"; private static final String RADIOLOGY_OBS_FORM_URL = "/module/radiology/radiologyObs.form?"; @Autowired RadiologyService radiologyService; @Autowired ObsService obsService; @Autowired RadiologyProperties radiologyProperties; @InitBinder void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Obs.class, new ObsEditor()); } /** * Get obs corresponding to given radiologyOrder and obs * * @param order order for which the obs should be returned * @param obs obs which should be returned * @return model and view populated with an obs matching the given criteria * @should populate model and view with obs for given obs and given valid radiology order */ @RequestMapping(method = RequestMethod.GET, params = "obsId") protected ModelAndView getObs(@RequestParam(value = "orderId", required = true) RadiologyOrder radiologyOrder, @RequestParam(value = "obsId", required = true) Obs obs) { return populateModelAndView(radiologyOrder, obs); } /** * Populate model and view given radiologyOrder and obs * * @param radiologyOrder to populate the model and view * @param obs to populate the model and view * @should populate the model and view for given radiology order with completed study and obs * @should populate the model and view for given radiology order without completed study and obs * @should populate the model and view for given obs with complex concept */ private ModelAndView populateModelAndView(RadiologyOrder radiologyOrder, Obs obs) { ModelAndView result = new ModelAndView(RADIOLOGY_OBS_FORM_PATH); List<Obs> previousObs = radiologyService.getObsByOrderId(radiologyOrder.getOrderId()); result.addObject("obs", obs); result.addObject("previousObs", previousObs); Study study = radiologyOrder.getStudy(); result.addObject("studyUID", study.isCompleted() ? study.getStudyInstanceUid() : null); result.addObject("dicomViewerUrl", getDicomViewerUrl(study)); if (obs.getId() != null && obs.getConcept() != null && obs.getConcept().isComplex()) { Obs complexObsAsHtmlView = obsService.getComplexObs(obs.getId(), WebConstants.HTML_VIEW); result.addObject("htmlView", complexObsAsHtmlView.getComplexData().getData()); Obs complexObsAsHyperlinkView = obsService.getComplexObs(obs.getId(), WebConstants.HYPERLINK_VIEW); result.addObject("hyperlinkView", complexObsAsHyperlinkView.getComplexData().getData()); } return result; } /** * Get dicom viewer URL for given study * * @param study study for the dicom viewer url * @should return dicom viewer url given completed study * @should return null given non completed study */ private String getDicomViewerUrl(Study study) { return study.isCompleted() ? radiologyProperties.getDicomViewerUrl() + "studyUID=" + study.getStudyInstanceUid() : null; } /** * Get new obs corresponding to given radiologyOrder * * @param radiologyOrder radiology order for which the obs should be returned * @return model and view populated with a new obs * @should populate model and view with new obs given a valid radiology order */ @RequestMapping(method = RequestMethod.GET) protected ModelAndView getNewObs( @RequestParam(value = "orderId", required = true) RadiologyOrder radiologyOrder) { Obs obs = new Obs(); obs.setOrder(radiologyOrder); obs.setPerson(radiologyOrder.getPatient()); obs.setEncounter(radiologyOrder.getEncounter()); return populateModelAndView(radiologyOrder, obs); } /** * * Void given obs corresponding to given http servlet request, http servlet response, radiologyOrder, obs, voidReason * * @param request the http servlet request with all parameters * @param response the http servlet response * @param radiologyOrder the corresponding radiology order * @param obs the obs * @param voidReason the reason the obs was voided for * @return ModelAndView for radiology obs form * @should void obs for given request, response, radiologyOrder, obs, and voidReason * @should not void obs with empty voiding reason * @should not void obs with voiding reason null */ @RequestMapping(method = RequestMethod.POST, params = "voidObs") protected ModelAndView voidObs(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "orderId", required = true) RadiologyOrder radiologyOrder, @RequestParam(value = "obsId", required = true) Obs obs, @RequestParam(value = "voidReason", required = true) String voidReason) { if (voidReason == null || voidReason.isEmpty()) { request.getSession().setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "Obs.void.reason.empty"); return populateModelAndView(radiologyOrder, obs); } obsService.voidObs(obs, voidReason); request.getSession().setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Obs.voidedSuccessfully"); return new ModelAndView("redirect:" + RADIOLOGY_OBS_FORM_URL + "orderId=" + radiologyOrder.getId() + "&obsId=" + obs.getId()); } /** * * Unvoid given obs corresponding to given http servlet request, http servlet response and obs * * @param request the http servlet request with all parameters * @param response the http servlet response * @param obs obs which should be unvoided * @return ModelAndView for radiology order list * @should unvoid voided obs for given request, response and obs */ @RequestMapping(method = RequestMethod.POST, params = "unvoidObs") protected ModelAndView unvoidObs(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "obsId", required = true) Obs obs) { obsService.unvoidObs(obs); request.getSession().setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Obs.unvoidedSuccessfully"); return new ModelAndView("redirect:" + RADIOLOGY_OBS_FORM_URL + "orderId=" + obs.getOrder().getId() + "&obsId=" + obs.getId()); } /** * Save obs corresponding to given http servlet request, http servlet response, editReason, radiologyOrder, obs, obsErrors * * @param request the http servlet request with all parameters * @param response the http servlet response * @param editReason reason why the obs was edited * @param radiologyOrder radiology order corresponding to the obs * @param obs the obs to be changed * @param obsErrors the result of the parameter binding * @return ModelAndView populated with obs matching the given criteria * @should return redirecting model and view for not authenticated user * @should return populated model and view for obs * @should return populated model and view for invalid obs * @should populate model and view with obs for occuring Exception */ @RequestMapping(method = RequestMethod.POST, params = "saveObs") protected ModelAndView saveObs(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "editReason", required = false) String editReason, @RequestParam(value = "orderId", required = true) RadiologyOrder radiologyOrder, @ModelAttribute("obs") Obs obs, BindingResult obsErrors) { if (Context.isAuthenticated()) { try { if (isObsValidToSave(obs, obsErrors, editReason)) { obs = obsService.saveObs(obs, editReason); request.getSession().setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Obs.saved"); } else { return populateModelAndView(radiologyOrder, obs, editReason); } } catch (Exception e) { request.getSession().setAttribute(WebConstants.OPENMRS_ERROR_ATTR, e.getMessage()); return populateModelAndView(radiologyOrder, obs, editReason); } } return new ModelAndView("redirect:" + RADIOLOGY_OBS_FORM_URL + "orderId=" + obs.getOrder().getId() + "&obsId=" + obs.getId()); } /** * Save obs corresponding to given http servlet request, http servlet response, editReason, radiologyOrder, obs, obsErrors * * @param request the http servlet request with all parameters * @param response the http servlet response * @param editReason reason why the obs was edited * @param radiologyOrder radiology order corresponding to the obs * @param obs the obs to be changed * @param obsErrors the result of the parameter binding * @return ModelAndView populated with obs matching the given criteria * @should return redirecting model and view for not authenticated user * @should return populated model and view for complex obs * @should return populated model and view for invalid complex obs * @should populate model and view with obs for occuring Exception */ @RequestMapping(method = RequestMethod.POST, params = "saveComplexObs") protected ModelAndView saveComplexObs(MultipartHttpServletRequest request, HttpServletResponse response, @RequestParam(value = "editReason", required = false) String editReason, @RequestParam(value = "orderId", required = true) RadiologyOrder radiologyOrder, @ModelAttribute("obs") Obs obs, BindingResult obsErrors) { if (Context.isAuthenticated()) { try { InputStream complexDataInputStream = openInputStreamForComplexDataFile( request.getFile("complexDataFile")); obs = populateObsWithComplexData(request.getFile("complexDataFile"), obs, complexDataInputStream); if (isObsValidToSave(obs, obsErrors, editReason)) { obs = obsService.saveObs(obs, editReason); request.getSession().setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Obs.saved"); } else { return populateModelAndView(radiologyOrder, obs, editReason); } complexDataInputStream.close(); } catch (Exception e) { request.getSession().setAttribute(WebConstants.OPENMRS_ERROR_ATTR, e.getMessage()); return populateModelAndView(radiologyOrder, obs, editReason); } } return new ModelAndView("redirect:" + RADIOLOGY_OBS_FORM_URL + "orderId=" + obs.getOrder().getId() + "&obsId=" + obs.getId()); } /** * Open input stream for complex data file * * @param complexDataFile the complex data file * @return input stream for complex data file * @throws IOException if stream could not be opened * @should open input stream for complex data file * @should throw exception if input stream could not be opened */ private InputStream openInputStreamForComplexDataFile(MultipartFile complexDataFile) throws IOException { if (complexDataFile == null) { throw new IOException("error.general"); } return complexDataFile.getInputStream(); } /** * Populate complex obs with complex data * * @param complexDataFile the obs should be populated with * @param obs to be populated * @param InputStream of the file * @return saved complex obs with complex data * @throws IOException * @should populate new obs with new complex data * @should populate obs with new complex data * @should throw exception for new obs with empty file */ private Obs populateObsWithComplexData(MultipartFile complexDataFile, Obs obs, InputStream complexDataInputStream) throws IOException { boolean isComplexDataFileNotNullAndNotEmpty = complexDataFile != null && !complexDataFile.isEmpty(); if (isComplexDataFileNotNullAndNotEmpty) { obs.setComplexData(new ComplexData(complexDataFile.getOriginalFilename(), complexDataInputStream)); return obs; } else if (obs.getId() != null) { obs.setComplexData(obsService.getComplexObs(obs.getId(), null).getComplexData()); return obs; } else { throw new IOException("Obs.invalidImage"); } } /** * Check if Obs is Valid * * @param obs to be validated * @param obsErrors the result of the parameter binding * @param editReason reason why the obs was edited * @return true if obs is valid * @should return true if obs is valid * @should return false if edit reason is empty and obs id not null * @should return false if edit reason is null and obs id not null * @should return false if validation of the obs validator fails */ private boolean isObsValidToSave(Obs obs, BindingResult obsErrors, String editReason) { if (obs.getObsId() != null && (editReason == null || editReason.isEmpty())) { obsErrors.reject("editReason", "Obs.edit.reason.empty"); return false; } new ObsValidator().validate(obs, obsErrors); if (obsErrors.hasErrors()) { return false; } return true; } /** * Populate model and view given radiologyOrder, obs and editReason * * @param radiologyOrder to populate the model and view * @param obs to populate the model and view * @param reason, why the obs was edited * @should populate model and view with edit reason */ private ModelAndView populateModelAndView(RadiologyOrder radiologyOrder, Obs obs, String editReason) { ModelAndView result = populateModelAndView(radiologyOrder, obs); return editReason == null ? result.addObject("editReason", "") : result.addObject("editReason", editReason); } }