@Override
  protected ResponseEntity<Object> handleMethodArgumentNotValid(
      MethodArgumentNotValidException ex,
      HttpHeaders headers,
      HttpStatus status,
      WebRequest request) {
    final List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
    final List<ObjectError> globalErrors = ex.getBindingResult().getGlobalErrors();

    StringBuilder errors = new StringBuilder();

    for (FieldError fieldError : fieldErrors) {
      errors
          .append(fieldError.getField())
          .append(": ")
          .append(fieldError.getDefaultMessage())
          .append("\n");
    }

    for (ObjectError globalError : globalErrors) {
      errors
          .append(globalError.getObjectName())
          .append(": ")
          .append(globalError.getDefaultMessage())
          .append("\n");
    }

    return new ResponseEntity<>(errors.toString(), headers, status);
  }
  protected void handleResultErrors(BindingResult result) throws EscreeningDataValidationException {
    if (result.hasErrors()) {
      ErrorBuilder<EscreeningDataValidationException> errorBuilder =
          ErrorBuilder.throwing(EscreeningDataValidationException.class);

      for (ObjectError objectError : result.getAllErrors()) {

        ErrorMessage errorMessage = new ErrorMessage();

        if (objectError instanceof FieldError) {
          errorMessage.setName(((FieldError) objectError).getField());
        } else {
          errorMessage.setName(objectError.getObjectName());
        }

        errorMessage.setDescription(objectError.getDefaultMessage());
        errorBuilder.toUser(errorMessage);
      }
      // set admin message and throw error
      errorBuilder
          .toAdmin(
              "BaseDashboardRestController.handleResultErrors:  called with "
                  + result.getAllErrors().size()
                  + " errors")
          .throwIt();
    }
  }
  @RequestMapping(method = RequestMethod.POST)
  public ModelAndView update(
      @Valid SearchElementEntity elementDefinition,
      BindingResult bindingResult,
      HttpServletRequest httpServletRequest,
      ServerHttpResponse response) {
    LOGGER.info(
        "Creating an filed element: "
            + elementDefinition.getClazz().getSimpleName()
            + " for preset: "
            + elementDefinition.getPreset().getSlug());

    ModelAndView model = new ModelAndView("admin/SearchElementDefinition/updateForm");

    if (bindingResult.hasErrors()) {
      LOGGER.error("Bindding has error...");
      for (ObjectError error : bindingResult.getAllErrors()) {
        LOGGER.error("Error: " + error.getDefaultMessage());
      }
      response.setStatusCode(HttpStatus.PRECONDITION_FAILED);
      return model;
    }
    try {
      elementDefinition = repository.save(elementDefinition);
    } catch (Exception e) {
      LOGGER.error("Could not save elementDefinition", e);
    }
    model.addObject("searchElementDefinition", elementDefinition);
    return model;
  }
Exemple #4
0
  @ExceptionHandler(MethodArgumentNotValidException.class)
  @ResponseBody
  public ResponseEntity<ErrorMessage> handleValidationException(MethodArgumentNotValidException e) {
    List<ObjectError> errors = e.getBindingResult().getAllErrors();
    List<String> messages = new ArrayList<String>();

    // WebServiceError webServiceError =
    // WebServiceError.build(WebServiceError.Type.VALIDATION_ERROR, errors.get(0).getObjectName() +
    // " " + errors.get(0).getDefaultMessage());

    for (ObjectError error : errors) {

      if (error instanceof FieldError) {
        FieldError fieldError = (FieldError) error;
        messages.add(
            fieldError.getField()
                + " "
                + fieldError.getRejectedValue()
                + " "
                + error.getDefaultMessage());
      } else {

        messages.add(error.toString());
      }
    }

    return new ResponseEntity<ErrorMessage>(new ErrorMessage(messages), HttpStatus.BAD_REQUEST);
  }
Exemple #5
0
 public static void printResultErrors(BindingResult result) {
   if (result.hasErrors()) {
     List<ObjectError> errors = result.getAllErrors();
     for (ObjectError error : errors)
       System.out.println(error.getObjectName() + ", " + error.getDefaultMessage());
   }
 }
  /**
   * AJAX Called once user is submitting upload form
   *
   * @param model
   * @param file - Uploaded file
   * @param comment - Comment for uploaded file
   * @return
   */
  @RequestMapping(method = RequestMethod.POST)
  public @ResponseBody JsonResponse uploadAction(
      @Valid @ModelAttribute(value = "image") Image image,
      @RequestParam(value = "captcha_challenge", required = true) String challenge,
      @RequestParam(value = "captcha_response", required = true) String response,
      BindingResult result,
      HttpServletRequest paramHttpServletRequest) {
    JsonResponse jsonResponse = new JsonResponse();
    String remoteAddr = paramHttpServletRequest.getRemoteAddr();
    ReCaptchaResponse reCaptchaResponse = recaptcha.checkAnswer(remoteAddr, challenge, response);
    if (!reCaptchaResponse.isValid()) {
      jsonResponse.setCaptchaError(
          context.getMessage("error.bad.captcha", null, Locale.getDefault()));
      return jsonResponse;
    }

    prepareImage(image);
    (new ImageValidator()).validate(image, result);
    if (!result.hasErrors()) {
      try {
        image.setBytes(image.getFile().getBytes());
        image.setContentType(image.getFile().getContentType());
        image = imageService.saveImage(image);
        jsonResponse.setResponse(paramHttpServletRequest.getRequestURL() + image.getId());
      } catch (Exception e) {
        log.error(e.getMessage());
      }
    } else {
      for (ObjectError error : result.getAllErrors()) {
        jsonResponse.appendError(context.getMessage(error.getCode(), null, Locale.getDefault()));
      }
    }
    return jsonResponse;
  }
  @ResourceMapping(value = "submitMeteruseinfoForm")
  public Resultmsg onSubmitMeteruseinfoForm(
      @ModelAttribute("meteruseinfo") Meteruseinfo meteruseinfo,
      BindingResult result,
      SessionStatus status,
      ResourceRequest request,
      ResourceResponse response) {
    Resultmsg msg = new Resultmsg();
    boolean isnew = true;
    if (request.getParameter("isnew") == null) {
      msg.setMsg("页面缺少新增或编辑标记 isnew");
    } else {
      isnew = Boolean.valueOf(request.getParameter("isnew"));
    }
    new MeteruseinfoValidator().validate(meteruseinfo, result);
    if (result.hasErrors()) {
      logger.error(result);
      StringBuilder sb = new StringBuilder();
      for (ObjectError err : result.getAllErrors()) {
        sb.append(err.getDefaultMessage());
      }
      msg.setMsg(sb.toString());
    } else {
      try {
        if (!StringUtils.hasLength(meteruseinfo.getBuildregioninfo().getRegionId())) {
          meteruseinfo.setBuildregioninfo(null);
        }
        Circuitinfo circuitinfo =
            circuitinfoService.getCircuitinfo(meteruseinfo.getCircuitinfo().getCircuitId());
        meteruseinfo.setCircuitinfo(circuitinfo);
        if ("系统生成".equals(meteruseinfo.getMeterId()) || "".equals(meteruseinfo.getMeterId())) {
          meteruseinfoService.addMeteruseinfo(meteruseinfo);
        } else {
          meteruseinfoService.updateMeteruseinfo(meteruseinfo);
        }

        // meteruseinfoService.saveOrUpdateMeteruseinfo(meteruseinfo);

        // 保存分类分项与装表关系数据
        if (StringUtils.hasLength(request.getParameter("energyItemcode"))) {
          String energyItemcode = request.getParameter("energyItemcode").trim();
          String resultId = request.getParameter("resultId").trim();
          Energyitemresult energyitemresult = new Energyitemresult();
          energyitemresult.setResultId(resultId);
          energyitemresult.setMeteruseinfo(meteruseinfo);
          Energyitemdict energyitemdict = energyitemdictService.getEnergyitemdict(energyItemcode);
          energyitemresult.setEnergyitemdict(energyitemdict);
          energyitemresultService.saveOrUpdateEnergyitemresult(energyitemresult);
        }
        status.setComplete();
        msg.setMsg(meteruseinfo.getMeterId());
        msg.setSuccess("true");
      } catch (Exception e) {
        msg.setMsg(e.getMessage());
        logger.error(e);
      }
    }
    return msg;
  }
 private void convertPasswordError(BindingResult result) {
   for (ObjectError error : result.getGlobalErrors()) {
     String msg = error.getDefaultMessage();
     if (SignupForm.PASSWORD_MISMATCH.equals(msg)) {
       if (!result.hasFieldErrors("repeatPassword")) {
         result.rejectValue("repeatPassword", SignupForm.PASSWORD_MISMATCH);
       }
     }
   }
 }
Exemple #9
0
 protected void handleBindingValidation(BindingResult bindingResult) throws MyException {
   if (bindingResult.hasErrors()) {
     List<ObjectError> list = bindingResult.getAllErrors();
     StringBuilder msg = new StringBuilder();
     for (ObjectError error : list) {
       msg.append(error.getDefaultMessage() + ";");
     }
     throw new MyException("0", msg.toString());
   }
 }
 protected String getViewWithBindingErrorMessages(
     final Model model, final BindingResult bindingErrors) {
   for (final ObjectError error : bindingErrors.getAllErrors()) {
     if (isTypeMismatchError(error)) {
       model.addAttribute(ERROR_MSG_TYPE, QUANTITY_INVALID_BINDING_MESSAGE_KEY);
     } else {
       model.addAttribute(ERROR_MSG_TYPE, error.getDefaultMessage());
     }
   }
   return ControllerConstants.Views.Fragments.Cart.AddToCartPopup;
 }
  /**
   * Helper method to extract unique error messages from a bind exception and format them
   *
   * @param errors the bind exception
   * @return the messages
   */
  protected Set<String> uniqueErrorMessages(BindException errors) {
    Set<String> messages = new LinkedHashSet<String>();
    for (Object objerr : errors.getAllErrors()) {
      ObjectError error = (ObjectError) objerr;
      String message = Context.getMessageSourceService().getMessage(error.getCode());

      if (error instanceof FieldError) {
        message = ((FieldError) error).getField() + ": " + message;
      }

      messages.add(message);
    }

    return messages;
  }
 @RequiresPermissions(value = "cartype:save")
 @RequestMapping(value = "/save", method = RequestMethod.POST)
 public String editCarType(
     CarType carType,
     BindingResult bindingResult,
     @RequestParam(value = "file") MultipartFile file,
     HttpSession httpSession) {
   if (bindingResult.hasErrors()) {
     for (ObjectError error : bindingResult.getAllErrors()) {
       System.out.println(error.getObjectName() + " : " + error.getDefaultMessage());
     }
   }
   carTypeService.updateCarType(carType, file, httpSession);
   return "redirect:/admin/cartype/list";
 }
 @Override
 public Message update(Orator object, BindingResult result) {
   if (result.hasErrors()) {
     Message oratorMessage = new Message("There is error in inserting the orator", false);
     List<String> errorOrator = new ArrayList<String>();
     for (ObjectError error : result.getAllErrors()) {
       errorOrator.add(error.getDefaultMessage());
     }
     oratorMessage.setErrors(errorOrator);
     return oratorMessage;
   } else {
     oratorRepository.save(object);
     Message oratorMessage = new Message("Orator save successfully", true);
     oratorMessage.setId(object.getIdOrator());
     return oratorMessage;
   }
 }
Exemple #14
0
 public static BaseResponse createResponse(HttpStatus status, BindingResult result) {
   BaseResponse response = new BaseResponse();
   if (result.hasErrors()) {
     response.setError(true);
     response.setHttpErrorCode(status.value());
     /* create an array of total error count */
     ArrayList<ErrorDTO> errors = new ArrayList<ErrorDTO>(result.getErrorCount());
     /* append all field errors */
     for (FieldError err : result.getFieldErrors()) {
       System.out.println(
           "I got field error for: "
               + err.getField()
               + ", message: "
               + err.getDefaultMessage()
               + ", code: "
               + err.getCode());
       ErrorDTO dto = new ErrorDTO(err.getField(), err.getCode(), err.getDefaultMessage());
       errors.add(dto);
     }
     /* append global errors now */
     for (ObjectError err : result.getGlobalErrors()) {
       System.out.println(
           "I got global error for: "
               + err.getObjectName()
               + ", message: "
               + err.getDefaultMessage()
               + ", code: "
               + err.getCode());
       ErrorDTO dto = new ErrorDTO(err.getObjectName(), err.getCode(), err.getDefaultMessage());
       errors.add(dto);
     }
     response.setErrors(errors);
   }
   return response;
 }
 /** 处理参数校验错误 */
 @ExceptionHandler({BindException.class})
 @ResponseStatus(value = HttpStatus.BAD_REQUEST)
 @ResponseBody
 public BaseResponseEntity<List<String>> handleException(
     BindException exception, HttpServletRequest request) {
   BindingResult bindingResult = exception.getBindingResult();
   List<ObjectError> objectErrors = bindingResult.getAllErrors();
   List<String> errorMessages = new LinkedList<String>();
   for (ObjectError objectError : objectErrors) {
     errorMessages.add(objectError.getDefaultMessage());
   }
   return BaseResponseEntity.build(
       HttpStatus.BAD_REQUEST.value(),
       APIStatus.INVALID_PARAMETER.getStatus(),
       APIStatus.INVALID_PARAMETER.name(),
       errorMessages,
       request);
 }
  @RequestMapping(method = RequestMethod.POST)
  public ModelAndView submitWorklog(
      @ModelAttribute("worklogWrapper") WorklogWrapper worklogWrapper,
      BindingResult errors,
      @PathVariable("user") String user,
      @RequestParam(value = "date", defaultValue = "") String date) {

    if (errors.hasErrors()) {
      List<ObjectError> l = errors.getAllErrors();

      for (ObjectError ob : l) {
        System.out.println("------ " + ob.getDefaultMessage());
      }
    }

    populateObjects(worklogWrapper.getWorklog(), user, date);
    worklogService.addWorklog(worklogWrapper.getWorklog());
    ModelAndView modelAndView =
        dataHolder.getModelAndView("redirect:/spring/" + user + "/showWorklog");
    return modelAndView;
  }
 @RequestMapping(value = "admin/user/useraddaction", method = RequestMethod.POST)
 public String addContact(
     @ModelAttribute("user") @Valid User user, BindingResult result, ModelMap m) {
   System.out.println("user : "******"lasterror", "");
   if (result.hasErrors()) {
     String errorOutput = "Registration failed : </br>";
     List<ObjectError> e = result.getAllErrors();
     for (ObjectError a : e) {
       errorOutput += a.getObjectName() + " : " + a.getDefaultMessage() + "</br>";
     }
     EMF.getHttpSession().setAttribute("lasterror", errorOutput);
     return "redirect:/app/admin/user/";
   }
   try {
     EMF.save(user);
     EMF.commit();
   } catch (Exception e) {
     m.addAttribute("error", e.getMessage());
   }
   return "redirect:/app/admin/user/";
 }
  /** 执行仪表属性提交 */
  @ResourceMapping(value = "submitMeteruseattributeForm")
  public Resultmsg onSubmitMeteruseattributeForm(
      @ModelAttribute("meteruseattribute") Meteruseattribute meteruseattribute,
      BindingResult result,
      SessionStatus status,
      ResourceRequest request,
      ResourceResponse response) {
    Resultmsg msg = new Resultmsg();

    String meterId = "";
    if (request.getParameter("meterId") != null) {
      meterId = request.getParameter("meterId");
      MeteruseattributeId id = new MeteruseattributeId();
      id.setMeterId(meterId);
      id.setMeterattrName(meteruseattribute.getId().getMeterattrName());
      meteruseattribute.setId(id);
    }

    new MeteruseattributeValidator().validate(meteruseattribute, result);
    if (result.hasErrors()) {
      logger.error(result);
      StringBuilder sb = new StringBuilder();
      for (ObjectError err : result.getAllErrors()) {
        sb.append(err.getDefaultMessage());
      }
      msg.setMsg(sb.toString());
    } else {
      try {
        meteruseinfoService.saveOrUpdateMeteruseattribute(meteruseattribute);
        status.setComplete();
        msg.setSuccess("true");
      } catch (Exception e) {
        logger.error(e);
        msg.setMsg(e.getMessage());
      }
    }
    return msg;
  }
 protected boolean isTypeMismatchError(final ObjectError error) {
   return error.getCode().equals(TYPE_MISMATCH_ERROR_CODE);
 }
Exemple #20
0
  /**
   * Binds data to this form - that is, handles form submission.
   *
   * @param data data to submit
   * @return a copy of this form filled with the new data
   */
  @SuppressWarnings("unchecked")
  public Form<T> bind(Map<String, String> data, String... allowedFields) {

    DataBinder dataBinder;
    Map<String, String> objectData = data;
    if (rootName == null) {
      dataBinder = new DataBinder(blankInstance());
    } else {
      dataBinder = new DataBinder(blankInstance(), rootName);
      objectData = new HashMap<>();
      for (String key : data.keySet()) {
        if (key.startsWith(rootName + ".")) {
          objectData.put(key.substring(rootName.length() + 1), data.get(key));
        }
      }
    }
    if (allowedFields.length > 0) {
      dataBinder.setAllowedFields(allowedFields);
    }
    SpringValidatorAdapter validator =
        new SpringValidatorAdapter(play.data.validation.Validation.getValidator());
    dataBinder.setValidator(validator);
    dataBinder.setConversionService(formatters.conversion);
    dataBinder.setAutoGrowNestedPaths(true);
    final Map<String, String> objectDataFinal = objectData;
    withRequestLocale(
        () -> {
          dataBinder.bind(new MutablePropertyValues(objectDataFinal));
          return null;
        });
    Set<ConstraintViolation<Object>> validationErrors;
    if (groups != null) {
      validationErrors = validator.validate(dataBinder.getTarget(), groups);
    } else {
      validationErrors = validator.validate(dataBinder.getTarget());
    }

    BindingResult result = dataBinder.getBindingResult();

    for (ConstraintViolation<Object> violation : validationErrors) {
      String field = violation.getPropertyPath().toString();
      FieldError fieldError = result.getFieldError(field);
      if (fieldError == null || !fieldError.isBindingFailure()) {
        try {
          result.rejectValue(
              field,
              violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName(),
              getArgumentsForConstraint(
                  result.getObjectName(), field, violation.getConstraintDescriptor()),
              getMessageForConstraintViolation(violation));
        } catch (NotReadablePropertyException ex) {
          throw new IllegalStateException(
              "JSR-303 validated property '"
                  + field
                  + "' does not have a corresponding accessor for data binding - "
                  + "check your DataBinder's configuration (bean property versus direct field access)",
              ex);
        }
      }
    }

    if (result.hasErrors() || result.getGlobalErrorCount() > 0) {
      Map<String, List<ValidationError>> errors = new HashMap<>();
      for (FieldError error : result.getFieldErrors()) {
        String key = error.getObjectName() + "." + error.getField();
        if (key.startsWith("target.") && rootName == null) {
          key = key.substring(7);
        }
        if (!errors.containsKey(key)) {
          errors.put(key, new ArrayList<>());
        }

        ValidationError validationError;
        if (error.isBindingFailure()) {
          ImmutableList.Builder<String> builder = ImmutableList.builder();
          Optional<Messages> msgs =
              Optional.of(Http.Context.current.get()).map(c -> messagesApi.preferred(c.request()));
          for (String code : error.getCodes()) {
            code = code.replace("typeMismatch", "error.invalid");
            if (!msgs.isPresent() || msgs.get().isDefinedAt(code)) {
              builder.add(code);
            }
          }
          validationError =
              new ValidationError(
                  key, builder.build().reverse(), convertErrorArguments(error.getArguments()));
        } else {
          validationError =
              new ValidationError(
                  key, error.getDefaultMessage(), convertErrorArguments(error.getArguments()));
        }
        errors.get(key).add(validationError);
      }

      List<ValidationError> globalErrors = new ArrayList<>();

      for (ObjectError error : result.getGlobalErrors()) {
        globalErrors.add(
            new ValidationError(
                "", error.getDefaultMessage(), convertErrorArguments(error.getArguments())));
      }

      if (!globalErrors.isEmpty()) {
        errors.put("", globalErrors);
      }

      return new Form(
          rootName, backedType, data, errors, Optional.empty(), groups, messagesApi, formatters);
    } else {
      Object globalError = null;
      if (result.getTarget() != null) {
        try {
          java.lang.reflect.Method v = result.getTarget().getClass().getMethod("validate");
          globalError = v.invoke(result.getTarget());
        } catch (NoSuchMethodException e) {
          // do nothing
        } catch (Throwable e) {
          throw new RuntimeException(e);
        }
      }
      if (globalError != null) {
        Map<String, List<ValidationError>> errors = new HashMap<>();
        if (globalError instanceof String) {
          errors.put("", new ArrayList<>());
          errors.get("").add(new ValidationError("", (String) globalError, new ArrayList()));
        } else if (globalError instanceof List) {
          for (ValidationError error : (List<ValidationError>) globalError) {
            List<ValidationError> errorsForKey = errors.get(error.key());
            if (errorsForKey == null) {
              errors.put(error.key(), errorsForKey = new ArrayList<>());
            }
            errorsForKey.add(error);
          }
        } else if (globalError instanceof Map) {
          errors = (Map<String, List<ValidationError>>) globalError;
        }
        return new Form(
            rootName, backedType, data, errors, Optional.empty(), groups, messagesApi, formatters);
      }
      return new Form(
          rootName,
          backedType,
          new HashMap<>(data),
          new HashMap<>(errors),
          Optional.ofNullable((T) result.getTarget()),
          groups,
          messagesApi,
          formatters);
    }
  }
  /**
   * Validates the given Patient.
   *
   * @param obj The patient to validate.
   * @param errors The patient to validate.
   * @see org.springframework.validation.Validator#validate(java.lang.Object,
   *     org.springframework.validation.Errors)
   * @should pass if the minimum required fields are provided and are valid
   * @should fail validation if gender is blank
   * @should fail validation if birthdate is blank
   * @should fail validation if birthdate makes patient 120 years old or older
   * @should fail validation if birthdate is a future date
   * @should fail validation if causeOfDeath is blank when patient is dead
   * @should fail if all name fields are empty or white space characters
   * @should fail if no identifiers are added
   * @should fail if all identifiers have been voided
   * @should fail if any name has more than 50 characters
   * @should fail validation if deathdate is a future date
   * @should fail if the deathdate is before the birthdate incase the patient is dead
   * @should reject a duplicate name
   * @should reject a duplicate address
   */
  public void validate(Object obj, Errors errors) {
    if (log.isDebugEnabled()) {
      log.debug(
          this.getClass().getName() + ": Validating patient data from the short patient form....");
    }

    ShortPatientModel shortPatientModel = (ShortPatientModel) obj;
    PersonName personName = shortPatientModel.getPersonName();

    // TODO We should be able to let developers and implementations to specify which person name
    // fields should be used to determine uniqueness

    // check if this name has a unique givenName, middleName and familyName combination
    for (PersonName possibleDuplicate : shortPatientModel.getPatient().getNames()) {
      // don't compare the name to itself
      if (OpenmrsUtil.nullSafeEquals(possibleDuplicate.getId(), personName.getId())) {
        continue;
      }

      if (OpenmrsUtil.nullSafeEqualsIgnoreCase(
              possibleDuplicate.getGivenName(), personName.getGivenName())
          && OpenmrsUtil.nullSafeEqualsIgnoreCase(
              possibleDuplicate.getMiddleName(), personName.getMiddleName())
          && OpenmrsUtil.nullSafeEqualsIgnoreCase(
              possibleDuplicate.getFamilyName(), personName.getFamilyName())) {
        errors.reject(
            "Patient.duplicateName",
            new Object[] {personName.getFullName()},
            personName.getFullName() + " is a duplicate name for the same patient");
      }
    }

    Errors nameErrors = new BindException(personName, "personName");
    new PersonNameValidator().validatePersonName(personName, nameErrors, false, true);

    if (nameErrors.hasErrors()) {
      // pick all the personName errors and bind them to the formObject
      Iterator<ObjectError> it = nameErrors.getAllErrors().iterator();
      Set<String> errorCodesWithNoArguments = new HashSet<String>();
      while (it.hasNext()) {
        ObjectError error = it.next();
        // don't show similar error message multiple times in the view
        // unless they take in arguments which will make them atleast different
        if (error.getCode() != null
            && (!errorCodesWithNoArguments.contains(error.getCode())
                || (error.getArguments() != null && error.getArguments().length > 0))) {
          errors.reject(error.getCode(), error.getArguments(), "");
          if (error.getArguments() == null || error.getArguments().length == 0) {
            errorCodesWithNoArguments.add(error.getCode());
          }
        }
      }
      // drop the collection
      errorCodesWithNoArguments = null;
    }

    // TODO We should be able to let developers and implementations to specify which
    // person address fields should be used to determine uniqueness

    // check if this address is unique
    PersonAddress personAddress = shortPatientModel.getPersonAddress();
    for (PersonAddress possibleDuplicate : shortPatientModel.getPatient().getAddresses()) {
      // don't compare the address to itself
      if (OpenmrsUtil.nullSafeEquals(possibleDuplicate.getId(), personAddress.getId())) {
        continue;
      }

      if (!possibleDuplicate.isBlank()
          && !personAddress.isBlank()
          && possibleDuplicate.toString().equalsIgnoreCase(personAddress.toString())) {
        errors.reject(
            "Patient.duplicateAddress",
            new Object[] {personAddress.toString()},
            personAddress.toString() + " is a duplicate address for the same patient");
      }
    }

    if (CollectionUtils.isEmpty(shortPatientModel.getIdentifiers())) {
      errors.reject("PatientIdentifier.error.insufficientIdentifiers");
    } else {
      boolean nonVoidedIdentifierFound = false;
      for (PatientIdentifier pId : shortPatientModel.getIdentifiers()) {
        // no need to validate unsaved identifiers that have been removed
        if (pId.getPatientIdentifierId() == null && pId.isVoided()) {
          continue;
        }

        if (!pId.isVoided()) {
          nonVoidedIdentifierFound = true;
        }

        new PatientIdentifierValidator().validate(pId, errors);
      }
      // if all the names are voided
      if (!nonVoidedIdentifierFound) {
        errors.reject("PatientIdentifier.error.insufficientIdentifiers");
      }
    }

    // Make sure they chose a gender
    if (StringUtils.isBlank(shortPatientModel.getPatient().getGender())) {
      errors.rejectValue("patient.gender", "Person.gender.required");
    }

    // check patients birthdate against future dates and really old dates
    if (shortPatientModel.getPatient().getBirthdate() != null) {
      if (shortPatientModel.getPatient().getBirthdate().after(new Date())) {
        errors.rejectValue("patient.birthdate", "error.date.future");
      } else {
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.YEAR, -120); // patient cannot be older than 120
        // years old
        if (shortPatientModel.getPatient().getBirthdate().before(c.getTime())) {
          errors.rejectValue("patient.birthdate", "error.date.nonsensical");
        }
      }
    } else {
      errors.rejectValue(
          "patient.birthdate",
          "error.required",
          new Object[] {Context.getMessageSourceService().getMessage("Person.birthdate")},
          "");
    }

    // validate the personAddress
    if (shortPatientModel.getPersonAddress() != null) {
      try {
        errors.pushNestedPath("personAddress");
        ValidationUtils.invokeValidator(
            new PersonAddressValidator(), shortPatientModel.getPersonAddress(), errors);
      } finally {
        errors.popNestedPath();
      }
    }

    if (shortPatientModel.getPatient().getDead()) {
      if (shortPatientModel.getPatient().getCauseOfDeath() == null) {
        errors.rejectValue("patient.causeOfDeath", "Person.dead.causeOfDeathNull");
      }

      if (shortPatientModel.getPatient().getDeathDate() != null) {
        if (shortPatientModel.getPatient().getDeathDate().after(new Date())) {
          errors.rejectValue("patient.deathDate", "error.date.future");
        }
        // death date has to be after birthdate if both are specified
        if (shortPatientModel.getPatient().getBirthdate() != null
            && shortPatientModel
                .getPatient()
                .getDeathDate()
                .before(shortPatientModel.getPatient().getBirthdate())) {
          errors.rejectValue("patient.deathDate", "error.deathdate.before.birthdate");
        }
      }
    }
  }
  /**
   * @should void the old person address and replace it with a new one when it is edited
   * @should void the old person address and replace it with a new one when it is edited
   * @should not void the existing address if there are no changes
   */
  public String post(
      UiSessionContext sessionContext,
      PageModel model,
      @RequestParam("patientId") @BindParams Patient patient,
      @BindParams PersonAddress address,
      @SpringBean("patientService") PatientService patientService,
      @RequestParam("appId") AppDescriptor app,
      @RequestParam("returnUrl") String returnUrl,
      @SpringBean("adminService") AdministrationService administrationService,
      HttpServletRequest request,
      @SpringBean("messageSourceService") MessageSourceService messageSourceService,
      Session session,
      @SpringBean("patientValidator") PatientValidator patientValidator,
      UiUtils ui)
      throws Exception {

    sessionContext.requireAuthentication();

    if (patient.getPersonAddress() != null && address != null) {
      PersonAddress currentAddress = patient.getPersonAddress();
      if (!currentAddress.equalsContent(address)) {
        // void the old address and replace it with the new one
        patient.addAddress(address);
        currentAddress.setVoided(true);
      }
    }

    NavigableFormStructure formStructure = RegisterPatientFormBuilder.buildFormStructure(app);

    BindingResult errors = new BeanPropertyBindingResult(patient, "patient");
    patientValidator.validate(patient, errors);
    RegistrationAppUiUtils.validateLatitudeAndLongitudeIfNecessary(address, errors);

    if (formStructure != null) {
      RegisterPatientFormBuilder.resolvePersonAttributeFields(
          formStructure, patient, request.getParameterMap());
    }

    if (!errors.hasErrors()) {
      try {
        // The person address changes get saved along as with the call to save patient
        patientService.savePatient(patient);
        InfoErrorMessageUtil.flashInfoMessage(
            request.getSession(),
            ui.message("registrationapp.editContactInfoMessage.success", patient.getPersonName()));

        return "redirect:" + returnUrl;
      } catch (Exception e) {
        log.warn("Error occurred while saving patient's contact info", e);
        session.setAttribute(
            UiCommonsConstants.SESSION_ATTRIBUTE_ERROR_MESSAGE, "registrationapp.save.fail");
      }

    } else {
      model.addAttribute("errors", errors);
      StringBuffer errorMessage =
          new StringBuffer(messageSourceService.getMessage("error.failed.validation"));
      errorMessage.append("<ul>");
      for (ObjectError error : errors.getAllErrors()) {
        errorMessage.append("<li>");
        errorMessage.append(
            messageSourceService.getMessage(
                error.getCode(), error.getArguments(), error.getDefaultMessage(), null));
        errorMessage.append("</li>");
      }
      errorMessage.append("</ul>");
      session.setAttribute(
          UiCommonsConstants.SESSION_ATTRIBUTE_ERROR_MESSAGE, errorMessage.toString());
    }

    addModelAttributes(model, patient, formStructure, administrationService, returnUrl);
    // redisplay the form
    return null;
  }