/**
   * Save obs corresponding to given http servlet request, http servlet response, radiologyOrder,
   * obs, obs, obsErrors
   *
   * @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 obsErrors the result of the parameter binding
   * @return ModelAndView populated with obs matching the given criteria
   * @should save obs with given parameters
   * @should return populated model and view if binding errors occur
   * @should return populated model and view if edit reason is empty and obs id not null
   * @should return populated model and view if edit reason is null and obs id not null
   * @should return redirecting model and view for not authenticated user
   * @should edit obs with edit reason and complex concept
   * @should edit obs with edit reason, complex concept and request which is an instance of
   *     multihttpserveletrequest
   * @should edit obs with edit reason concept not complex and request which is an instance of
   *     multihttpserveletrequest
   * @should populate model and view with obs occuring thrown APIException
   */
  @RequestMapping(
      value = "/module/radiology/radiologyObs.form",
      method = RequestMethod.POST,
      params = "saveObs")
  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) {

    HttpSession httpSession = request.getSession();

    new ObsValidator().validate(obs, obsErrors);

    if (obsErrors.hasErrors()) {
      return populateModelAndView(radiologyOrder, obs);
    }
    if (Context.isAuthenticated()) {

      try {
        // if the user is just editing the obs
        if (obs.getObsId() != null && (editReason == null || editReason.isEmpty())) {
          obsErrors.reject("editReason", "Obs.edit.reason.empty");

          return populateModelAndView(radiologyOrder, obs);
        }

        if (obs.getConcept().isComplex()) {
          if (request instanceof MultipartHttpServletRequest) {
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            MultipartFile complexDataFile = multipartRequest.getFile("complexDataFile");
            if (complexDataFile != null && !complexDataFile.isEmpty()) {
              InputStream complexDataInputStream = complexDataFile.getInputStream();

              ComplexData complexData =
                  new ComplexData(complexDataFile.getOriginalFilename(), complexDataInputStream);

              obs.setComplexData(complexData);

              // the handler on the obs.concept is called
              // with
              // the given complex data
              obsService.saveObs(obs, editReason);
              updateReadingPhysician(radiologyOrder.getStudy());
              complexDataInputStream.close();
            }
          }
        } else {
          obsService.saveObs(obs, editReason);
          updateReadingPhysician(radiologyOrder.getStudy());
        }
        httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "Obs.saved");
      } catch (APIException e) {
        httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, e.getMessage());
        return populateModelAndView(radiologyOrder, obs);
      } catch (IOException e) {
        return populateModelAndView(radiologyOrder, obs);
      }
    }
    return new ModelAndView(
        "redirect:"
            + RADIOLOGY_OBS_FORM_URL
            + "orderId="
            + obs.getOrder().getId()
            + "&obsId="
            + obs.getId());
  }