@Override
 public boolean equals(Object o) {
   if (o == null || !(o instanceof Diagnosis)) {
     return false;
   }
   Diagnosis other = (Diagnosis) o;
   return OpenmrsUtil.nullSafeEquals(diagnosis, other.getDiagnosis())
       && OpenmrsUtil.nullSafeEquals(order, other.getOrder())
       && OpenmrsUtil.nullSafeEquals(certainty, other.getCertainty());
 }
 private static boolean regimenComponentIsTheSameAsDrugOrderExcludingDates(
     DrugOrder rc, DrugOrder doTmp) {
   if (rc.getDrug() != null
       && doTmp.getDrug() != null
       && rc.getDrug().getDrugId().intValue() != doTmp.getDrug().getDrugId().intValue())
     return false;
   if (!OpenmrsUtil.nullSafeEquals(rc.getConcept(), doTmp.getConcept())) return false;
   if (!OpenmrsUtil.nullSafeEquals(rc.getDose(), doTmp.getDose())) return false;
   if (!OpenmrsUtil.nullSafeEquals(rc.getFrequency(), doTmp.getFrequency())) return false;
   if (!OpenmrsUtil.nullSafeEquals(rc.getUnits(), doTmp.getUnits())) return false;
   return true;
 }
  /**
   * Checks that a given concept map type object is valid.
   *
   * @see org.springframework.validation.Validator#validate(java.lang.Object,
   *     org.springframework.validation.Errors)
   * @should fail if the concept map type object is null
   * @should fail if the name is null
   * @should fail if the name is an empty string
   * @should fail if the name is a white space character
   * @should fail if the concept map type name is a duplicate
   * @should pass if the name is unique amongst all concept map type names
   * @should pass validation if field lengths are correct
   * @should fail validation if field lengths are not correct
   */
  public void validate(Object obj, Errors errors) {

    if (obj == null || !(obj instanceof ConceptMapType)) {
      throw new IllegalArgumentException(
          "The parameter obj should not be null and must be of type" + ConceptMapType.class);
    }

    ConceptMapType conceptMapType = (ConceptMapType) obj;
    String name = conceptMapType.getName();
    if (!StringUtils.hasText(name)) {
      errors.rejectValue(
          "name",
          "ConceptMapType.error.nameRequired",
          "The name property is required for a concept map type");
      return;
    }

    name = name.trim();
    ConceptMapType duplicate = Context.getConceptService().getConceptMapTypeByName(name);
    if (duplicate != null
        && !OpenmrsUtil.nullSafeEquals(duplicate.getUuid(), conceptMapType.getUuid())) {
      errors.rejectValue(
          "name", "ConceptMapType.duplicate.name", "Duplicate concept map type name: " + name);
    }
    ValidateUtil.validateFieldLengths(
        errors, obj.getClass(), "name", "description", "retireReason");
  }
 @PropertyGetter("concept")
 public Object getConcept(PersonAttributeType delegate) {
   if (OpenmrsUtil.nullSafeEquals(delegate.getFormat(), Concept.class.getCanonicalName())) {
     Concept concept = Context.getConceptService().getConcept(delegate.getForeignKey());
     return ConversionUtil.convertToRepresentation(concept, Representation.FULL);
   }
   return null;
 }
    public boolean matches(Obs obs) {

      if (!obs.getConcept().getConceptId().equals(conceptId)) {
        return false;
      }

      return OpenmrsUtil.nullSafeEquals(
          TestUtil.valueAsStringHelper(value), obs.getValueAsString(Context.getLocale()));
    }
  /**
   * @see
   *     org.openmrs.module.kenyacore.metadata.handler.ObjectMergeHandler#merge(org.openmrs.OpenmrsObject,
   *     org.openmrs.OpenmrsObject)
   */
  @Override
  public void merge(GlobalProperty existing, GlobalProperty incoming) {
    boolean datatypeMatches =
        OpenmrsUtil.nullSafeEquals(
            existing.getDatatypeClassname(), incoming.getDatatypeClassname());

    // Global properties don't really distinguish between blank and null values since the UI doesn't
    // let a user
    // distinguish between the two
    Object incomingValue = incoming.getValue();
    boolean incomingHasNoValue =
        incomingValue == null
            || (incomingValue instanceof String && StringUtils.isEmpty((String) incomingValue));

    if (existing.getValue() != null && incomingHasNoValue && datatypeMatches) {
      incoming.setValue(existing.getValue());
    }
  }
  /**
   * 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");
        }
      }
    }
  }
  /** @see org.openmrs.api.EncounterService#saveEncounter(org.openmrs.Encounter) */
  public Encounter saveEncounter(Encounter encounter) throws APIException {

    // if authenticated user is not supposed to edit encounter of certain type
    if (!canEditEncounter(encounter, null)) {
      throw new APIException(
          "Encounter.error.privilege.required.edit",
          new Object[] {encounter.getEncounterType().getEditPrivilege()});
    }

    // If new encounter, try to assign a visit using the registered visit assignment handler.
    if (encounter.getEncounterId() == null) {

      // Am using Context.getEncounterService().getActiveEncounterVisitHandler() instead of just
      // getActiveEncounterVisitHandler() for modules which may want to AOP around this call.
      EncounterVisitHandler encounterVisitHandler =
          Context.getEncounterService().getActiveEncounterVisitHandler();
      if (encounterVisitHandler != null) {
        encounterVisitHandler.beforeCreateEncounter(encounter);

        // If we have been assigned a new visit, persist it.
        if (encounter.getVisit() != null && encounter.getVisit().getVisitId() == null) {
          Context.getVisitService().saveVisit(encounter.getVisit());
        }
      }
    }

    boolean isNewEncounter = false;
    Date newDate = encounter.getEncounterDatetime();
    Date originalDate = null;
    Location newLocation = encounter.getLocation();
    Location originalLocation = null;
    // check permissions
    if (encounter.getEncounterId() == null) {
      isNewEncounter = true;
      Context.requirePrivilege(PrivilegeConstants.ADD_ENCOUNTERS);
    } else {
      Context.requirePrivilege(PrivilegeConstants.EDIT_ENCOUNTERS);
    }

    // This must be done after setting dateCreated etc on the obs because
    // of the way the ORM tools flush things and check for nullity
    // This also must be done before the save encounter so we can use the
    // orig date
    // after the save
    Patient p = encounter.getPatient();

    if (!isNewEncounter) {
      // fetch the datetime from the database prior to saving for this
      // encounter
      // to see if it has changed and change all obs after saving if so
      originalDate = dao.getSavedEncounterDatetime(encounter);
      if (encounter.getLocation() != null) {
        originalLocation = dao.getSavedEncounterLocation(encounter);
      }
      // Our data model duplicates the patient column to allow for
      // observations to
      // not have to look up the parent Encounter to find the patient
      // Therefore, encounter.patient must always equal
      // encounter.observations[0-n].patient

      // If we are changing encounter.encounterDatetime, then we need to
      // also apply that
      // to Obs that inherited their obsDatetime from the encounter in the
      // first place

      for (Obs obs : encounter.getAllObs(true)) {
        // if the date was changed
        if (OpenmrsUtil.compare(originalDate, newDate) != 0
            && OpenmrsUtil.compare(obs.getObsDatetime(), originalDate) == 0) {

          // if the obs datetime is the same as the
          // original encounter datetime, fix it
          obs.setObsDatetime(newDate);
        }

        if (!OpenmrsUtil.nullSafeEquals(newLocation, originalLocation)
            && obs.getLocation().equals(originalLocation)) {
          obs.setLocation(newLocation);
        }

        // if the Person in the obs doesn't match the Patient in the
        // encounter, fix it
        if (!obs.getPerson().getPersonId().equals(p.getPatientId())) {
          obs.setPerson(p);
        }
      }
    }
    // same goes for Orders
    for (Order o : encounter.getOrders()) {
      if (!p.equals(o.getPatient())) {
        o.setPatient(p);
      }
    }

    // do the actual saving to the database
    dao.saveEncounter(encounter);

    // save the new orders
    for (Order o : encounter.getOrders()) {
      if (o.getOrderId() == null) {
        Context.getOrderService().saveOrder(o, null);
      }
    }
    return encounter;
  }
 /**
  * Convenience method for checking whether this is an index Term.
  *
  * @return true if the name is marked as an index term, otherwise false
  * @since Version 1.7
  */
 public Boolean isIndexTerm() {
   return OpenmrsUtil.nullSafeEquals(getConceptNameType(), ConceptNameType.INDEX_TERM);
 }
 /**
  * Convenience method for determining whether this is a short name.
  *
  * @return true if the name is marked as a short name, otherwise false
  */
 public Boolean isShort() {
   return OpenmrsUtil.nullSafeEquals(getConceptNameType(), ConceptNameType.SHORT);
 }
 /**
  * Checks whether the concept name is explicitly marked as fully specified
  *
  * @return true if the name is marked as 'fully specified' otherwise false
  * @since Version 1.7
  */
 public Boolean isFullySpecifiedName() {
   return OpenmrsUtil.nullSafeEquals(getConceptNameType(), ConceptNameType.FULLY_SPECIFIED);
 }
  @ModelAttribute("command")
  public FormEntrySession getFormEntrySession(
      HttpServletRequest request,
      // @RequestParam doesn't pick up query parameters (in the url) in a POST, so I'm handling
      // encounterId, modeParam, and which specially
      /*@RequestParam(value="mode", required=false) String modeParam,*/
      /*@RequestParam(value="encounterId", required=false) Integer encounterId,*/
      /*@RequestParam(value="which", required=false) String which,*/
      @RequestParam(value = "patientId", required = false) Integer patientId,
      /*@RequestParam(value="personId", required=false) Integer personId,*/
      @RequestParam(value = "formId", required = false) Integer formId,
      @RequestParam(value = "htmlformId", required = false) Integer htmlFormId,
      @RequestParam(value = "returnUrl", required = false) String returnUrl,
      @RequestParam(value = "formModifiedTimestamp", required = false) Long formModifiedTimestamp,
      @RequestParam(value = "encounterModifiedTimestamp", required = false)
          Long encounterModifiedTimestamp)
      throws Exception {

    long ts = System.currentTimeMillis();

    Mode mode = Mode.VIEW;

    Integer personId = null;

    if (StringUtils.hasText(request.getParameter("personId"))) {
      personId = Integer.valueOf(request.getParameter("personId"));
    }

    String modeParam = request.getParameter("mode");
    if ("enter".equalsIgnoreCase(modeParam)) {
      mode = Mode.ENTER;
    } else if ("edit".equalsIgnoreCase(modeParam)) {
      mode = Mode.EDIT;
    }

    Patient patient = null;
    Encounter encounter = null;
    Form form = null;
    HtmlForm htmlForm = null;

    if (StringUtils.hasText(request.getParameter("encounterId"))) {

      Integer encounterId = Integer.valueOf(request.getParameter("encounterId"));
      encounter = Context.getEncounterService().getEncounter(encounterId);
      if (encounter == null)
        throw new IllegalArgumentException("No encounter with id=" + encounterId);
      patient = encounter.getPatient();
      patientId = patient.getPatientId();
      personId = patient.getPersonId();

      if (formId
          != null) { // I think formId is allowed to differ from encounter.form.id because of
                     // HtmlFormFlowsheet
        form = Context.getFormService().getForm(formId);
        htmlForm = HtmlFormEntryUtil.getService().getHtmlFormByForm(form);
        if (htmlForm == null)
          throw new IllegalArgumentException("No HtmlForm associated with formId " + formId);
      } else {
        form = encounter.getForm();
        htmlForm = HtmlFormEntryUtil.getService().getHtmlFormByForm(encounter.getForm());
        if (htmlForm == null)
          throw new IllegalArgumentException(
              "The form for the specified encounter ("
                  + encounter.getForm()
                  + ") does not have an HtmlForm associated with it");
      }

    } else { // no encounter specified

      // get person from patientId/personId (register module uses patientId, htmlformentry uses
      // personId)
      if (patientId != null) {
        personId = patientId;
      }
      if (personId != null) {
        patient = Context.getPatientService().getPatient(personId);
      }

      // determine form
      if (htmlFormId != null) {
        htmlForm = HtmlFormEntryUtil.getService().getHtmlForm(htmlFormId);
      } else if (formId != null) {
        form = Context.getFormService().getForm(formId);
        htmlForm = HtmlFormEntryUtil.getService().getHtmlFormByForm(form);
      }
      if (htmlForm == null) {
        throw new IllegalArgumentException(
            "You must specify either an htmlFormId or a formId for a valid html form");
      }

      String which = request.getParameter("which");
      if (StringUtils.hasText(which)) {
        if (patient == null)
          throw new IllegalArgumentException(
              "Cannot specify 'which' without specifying a person/patient");
        List<Encounter> encs =
            Context.getEncounterService()
                .getEncounters(
                    patient, null, null, null, Collections.singleton(form), null, null, false);
        if (which.equals("first")) {
          encounter = encs.get(0);
        } else if (which.equals("last")) {
          encounter = encs.get(encs.size() - 1);
        } else {
          throw new IllegalArgumentException("which must be 'first' or 'last'");
        }
      }
    }

    if (mode != Mode.ENTER && patient == null)
      throw new IllegalArgumentException(
          "No patient with id of personId=" + personId + " or patientId=" + patientId);

    FormEntrySession session = null;
    if (mode == Mode.ENTER && patient == null) {
      patient = new Patient();
    }
    if (encounter != null) {
      session = new FormEntrySession(patient, encounter, mode, htmlForm);
    } else {
      session = new FormEntrySession(patient, htmlForm);
    }

    if (StringUtils.hasText(returnUrl)) {
      session.setReturnUrl(returnUrl);
    }

    // Since we're not using a sessionForm, we need to check for the case where the underlying form
    // was modified while a user was filling a form out
    if (formModifiedTimestamp != null) {
      if (!OpenmrsUtil.nullSafeEquals(formModifiedTimestamp, session.getFormModifiedTimestamp())) {
        throw new RuntimeException(
            Context.getMessageSourceService()
                .getMessage("htmlformentry.error.formModifiedBeforeSubmission"));
      }
    }

    // Since we're not using a sessionForm, we need to make sure this encounter hasn't been modified
    // since the user opened it
    if (encounter != null) {
      if (encounterModifiedTimestamp != null
          && !OpenmrsUtil.nullSafeEquals(
              encounterModifiedTimestamp, session.getEncounterModifiedTimestamp())) {
        throw new RuntimeException(
            Context.getMessageSourceService()
                .getMessage("htmlformentry.error.encounterModifiedBeforeSubmission"));
      }
    }

    Context.setVolatileUserData(FORM_IN_PROGRESS_KEY, session);

    log.info("Took " + (System.currentTimeMillis() - ts) + " ms");

    return session;
  }