/**
   * Processes requests to unretire concept reference terms
   *
   * @param request the {@link WebRequest} object
   * @param conceptReferenceTermModel the concept reference term model object for the term to
   *     unretire
   * @param retireReason the reason why the concept reference term is being unretired
   * @return the url to redirect to
   */
  @RequestMapping(
      method = RequestMethod.POST,
      value = "/admin/concepts/unretireConceptReferenceTerm")
  public String unretireConceptReferenceTerm(
      WebRequest request,
      @ModelAttribute(value = "conceptReferenceTermModel")
          ConceptReferenceTermModel conceptReferenceTermModel) {

    try {
      ConceptReferenceTerm conceptReferenceTerm =
          conceptReferenceTermModel.getConceptReferenceTerm();
      Context.getConceptService().unretireConceptReferenceTerm(conceptReferenceTerm);
      if (log.isDebugEnabled()) {
        log.debug("Unretired concept reference term with id: " + conceptReferenceTerm.getId());
      }
      request.setAttribute(
          WebConstants.OPENMRS_MSG_ATTR,
          Context.getMessageSourceService().getMessage("ConceptReferenceTerm.unretired"),
          WebRequest.SCOPE_SESSION);

      return "redirect:"
          + CONCEPT_REFERENCE_TERM_FORM_URL
          + ".form?conceptReferenceTermId="
          + conceptReferenceTerm.getConceptReferenceTermId();
    } catch (APIException e) {
      log.error("Error occurred while unretiring concept reference term", e);
      request.setAttribute(
          WebConstants.OPENMRS_ERROR_ATTR,
          Context.getMessageSourceService().getMessage("ConceptReferenceTerm.unretire.error"),
          WebRequest.SCOPE_SESSION);
    }

    // an error occurred, show the form
    return CONCEPT_REFERENCE_TERM_FORM;
  }
  /**
   * Processes requests to retire concept reference terms
   *
   * @param request the {@link WebRequest} object
   * @param conceptReferenceTermModel the concept reference term model for the term to retire
   * @param retireReason the reason why the concept reference term is being retired
   * @return the url to redirect to
   */
  @RequestMapping(method = RequestMethod.POST, value = "/admin/concepts/retireConceptReferenceTerm")
  public String retireConceptReferenceTerm(
      WebRequest request,
      @ModelAttribute(value = "conceptReferenceTermModel")
          ConceptReferenceTermModel conceptReferenceTermModel,
      @RequestParam(required = false, value = "retireReason") String retireReason) {

    if (!StringUtils.hasText(retireReason)) {
      retireReason = Context.getMessageSourceService().getMessage("general.default.retireReason");
    }

    try {
      ConceptReferenceTerm conceptReferenceTerm =
          conceptReferenceTermModel.getConceptReferenceTerm();
      Context.getConceptService().retireConceptReferenceTerm(conceptReferenceTerm, retireReason);
      if (log.isDebugEnabled()) {
        log.debug("Retired concept reference term with id: " + conceptReferenceTerm.getId());
      }
      request.setAttribute(
          WebConstants.OPENMRS_MSG_ATTR,
          Context.getMessageSourceService().getMessage("ConceptReferenceTerm.retired"),
          WebRequest.SCOPE_SESSION);

      return "redirect:" + FIND_CONCEPT_REFERENCE_TERM_URL;
    } catch (APIException e) {
      log.error("Error occurred while retiring concept reference term", e);
      request.setAttribute(
          WebConstants.OPENMRS_ERROR_ATTR,
          Context.getMessageSourceService().getMessage("ConceptReferenceTerm.retire.error"),
          WebRequest.SCOPE_SESSION);
    }

    // an error occurred
    return CONCEPT_REFERENCE_TERM_FORM;
  }
  public DataObject simplifyReferenceTerm(ConceptReferenceTerm term) throws Exception {

    List<Object> propertyNamesAndValues = new ArrayList<Object>();

    if (term == null
        || StringUtils.isBlank(term.getCode())
        || StringUtils.isEmpty(term.getCode())) {

      propertyNamesAndValues.add("termCode");
      propertyNamesAndValues.add("");
      propertyNamesAndValues.add("termId");
      propertyNamesAndValues.add("");
      propertyNamesAndValues.add("termName");
      propertyNamesAndValues.add("No Snomed CT Reference Terms Mapped To This Concept");

    } else {

      propertyNamesAndValues.add("termCode");
      propertyNamesAndValues.add((term.getCode()));
      propertyNamesAndValues.add("termId");
      propertyNamesAndValues.add((term.getId()));

      if (term.getName() != null) {
        propertyNamesAndValues.add("termName");
        propertyNamesAndValues.add(term.getName());
      }
    }
    DataObject dataObject = DataObject.create(propertyNamesAndValues);
    return dataObject;
  }
 private void addTRCodingsForReferenceTerms(
     Concept concept,
     IdMappingsRepository idMappingsRepository,
     CodeableConceptDt codeableConcept,
     ConceptMap mapping) {
   ConceptReferenceTerm conceptReferenceTerm = mapping.getConceptReferenceTerm();
   IdMapping idMapping = idMappingsRepository.findByInternalId(conceptReferenceTerm.getUuid());
   if (idMapping != null) {
     addFHIRCoding(
         codeableConcept,
         conceptReferenceTerm.getCode(),
         idMapping.getUri(),
         concept.getName().getName());
   }
 }
    /**
     * Constructor that creates a concept reference term model object from the specified term
     *
     * @param conceptReferenceTerm
     */
    @SuppressWarnings("unchecked")
    public ConceptReferenceTermModel(ConceptReferenceTerm conceptReferenceTerm) {
      this.conceptReferenceTerm = conceptReferenceTerm;
      ArrayList<ConceptReferenceTermMap> maps = null;
      if (conceptReferenceTerm.getConceptReferenceTermMaps().size() == 0) {
        maps = new ArrayList<ConceptReferenceTermMap>();
        maps.add(new ConceptReferenceTermMap(null, null));
      } else {
        maps =
            new ArrayList<ConceptReferenceTermMap>(
                conceptReferenceTerm.getConceptReferenceTermMaps());
      }

      termMaps =
          ListUtils.lazyList(maps, FactoryUtils.instantiateFactory(ConceptReferenceTermMap.class));
    }
  private HashMap<ConceptReferenceTerm, List<Concept>> getAssociatedConceptsToRefTerms(
      Set<ConceptReferenceTerm> terms) {

    ConceptService conceptService = (ConceptService) Context.getService(ConceptService.class);
    HashMap<ConceptReferenceTerm, List<Concept>> hmconceptsToRefTerms =
        new HashMap<ConceptReferenceTerm, List<Concept>>();

    for (ConceptReferenceTerm refTerm : terms) {

      List<Concept> mappedConcept =
          conceptService.getConceptsByMapping(
              refTerm.getCode(), refTerm.getConceptSource().getName(), false);
      hmconceptsToRefTerms.put(refTerm, mappedConcept);
    }
    return hmconceptsToRefTerms;
  }
  @SuppressWarnings("unchecked")
  @ModelAttribute("referenceTermMappingsToThisTerm")
  public List<ConceptReferenceTermMap> getConceptMappingsToThisTerm(
      @ModelAttribute ConceptReferenceTerm conceptReferenceTerm) {
    if (conceptReferenceTerm.getConceptReferenceTermId() != null) {
      return Context.getConceptService().getReferenceTermMappingsTo(conceptReferenceTerm);
    }

    return ListUtils.EMPTY_LIST;
  }
  /**
   * Processes requests to save/update a concept reference term
   *
   * @param request the {@link WebRequest} object
   * @param conceptReferenceTermModel the concept reference term object to save/update
   * @param result the {@link BindingResult} object
   * @return the url to redirect to
   */
  @RequestMapping(method = RequestMethod.POST, value = CONCEPT_REFERENCE_TERM_FORM_URL)
  public String saveConceptReferenceTerm(
      WebRequest request,
      @ModelAttribute(value = "conceptReferenceTermModel")
          ConceptReferenceTermModel conceptReferenceTermModel,
      BindingResult result) {

    ConceptReferenceTerm conceptReferenceTerm = conceptReferenceTermModel.getConceptReferenceTerm();
    // add all the term maps
    // store ids of already mapped terms so that we don't map a term multiple times
    Set<Integer> mappedTermIds = null;
    for (int x = 0; x < conceptReferenceTermModel.getTermMaps().size(); x++) {
      if (mappedTermIds == null) {
        mappedTermIds = new HashSet<Integer>();
      }
      ConceptReferenceTermMap map = conceptReferenceTermModel.getTermMaps().get(x);

      if (map != null && map.getTermB() != null) {
        // skip past this mapping because its term is already in use by another mapping for this
        // term
        if (!mappedTermIds.add(map.getTermB().getConceptReferenceTermId())) {
          continue;
        }

        if (request.getParameter("_termMaps[" + x + "].exists") == null) {
          // because of the _termMap[x].exists input name in the jsp, the value will be null for
          // deleted maps, remove the map.
          conceptReferenceTerm.removeConceptReferenceTermMap(map);
        } else {
          if (map.getConceptMapType() == null) {
            result.rejectValue(
                "termMaps[" + x + "]",
                "ConceptReferenceTerm.error.mapTypeRequired",
                "Concept Map Type is required");
            log.warn("Concept Map Type is required");
            break;
          } else if (map.getTermB().equals(conceptReferenceTerm)) {
            result.rejectValue(
                "termMaps[" + x + "]",
                "ConceptReferenceTerm.map.sameTerm",
                "Cannot map a concept reference term to itself");
            log.warn("Cannot map a concept reference term to itself");
            break;
          } else if (!conceptReferenceTerm.getConceptReferenceTermMaps().contains(map)) {
            conceptReferenceTerm.addConceptReferenceTermMap(map);
          }
        }
      }
    }

    // if there are errors  with the term
    if (!result.hasErrors()) {
      try {
        result.pushNestedPath("conceptReferenceTerm");
        ValidationUtils.invokeValidator(
            new ConceptReferenceTermValidator(), conceptReferenceTerm, result);
        ValidationUtils.invokeValidator(
            new ConceptReferenceTermWebValidator(), conceptReferenceTerm, result);
      } finally {
        result.popNestedPath();
      }
    }

    if (!result.hasErrors()) {
      try {
        conceptReferenceTerm =
            Context.getConceptService().saveConceptReferenceTerm(conceptReferenceTerm);
        if (log.isDebugEnabled()) {
          log.debug("Saved concept reference term: " + conceptReferenceTerm.toString());
        }
        request.setAttribute(
            WebConstants.OPENMRS_MSG_ATTR, "ConceptReferenceTerm.saved", WebRequest.SCOPE_SESSION);
        return "redirect:"
            + CONCEPT_REFERENCE_TERM_FORM_URL
            + ".form?conceptReferenceTermId="
            + conceptReferenceTerm.getConceptReferenceTermId();
      } catch (APIException e) {
        log.error("Error while saving concept reference term", e);
        request.setAttribute(
            WebConstants.OPENMRS_ERROR_ATTR,
            "ConceptReferenceTerm.save.error",
            WebRequest.SCOPE_SESSION);
      }
    }

    return CONCEPT_REFERENCE_TERM_FORM;
  }