public void get(
      UiSessionContext sessionContext,
      PageModel model,
      @RequestParam("patientId") Patient patient,
      @RequestParam("appId") AppDescriptor app,
      @RequestParam(value = "returnUrl", required = false) String returnUrl,
      @SpringBean("adminService") AdministrationService administrationService)
      throws Exception {

    sessionContext.requireAuthentication();

    NavigableFormStructure formStructure = RegisterPatientFormBuilder.buildFormStructure(app);
    addModelAttributes(model, patient, formStructure, administrationService, returnUrl);
  }
  public List<String> search(UiSessionContext context, @RequestParam("id") String query)
      throws Exception {

    Locale locale = context.getLocale();

    List<ConceptSearchResult> hits = Context.getConceptService().getConcepts(query, locale, true);
    if (hits.size() > 100) {
      hits = hits.subList(0, 100);
    }

    List<String> list = new ArrayList<String>();

    Gson gson = new Gson();
    for (ConceptSearchResult hit : hits) {
      list.add(gson.toJson(simplifyConcept(hit.getConcept(), locale)));
    }

    return list;
  }
  public List<String> getAncestors(
      UiSessionContext context,
      @RequestParam("termId") String termId,
      @RequestParam("conceptId") String conceptId,
      @RequestParam("updateBy") String updateBy)
      throws Exception {

    Locale locale = context.getLocale();
    ConceptService conceptService = (ConceptService) Context.getService(ConceptService.class);

    ConceptManagementAppsProperties conceptManagementAppsProperties =
        new ConceptManagementAppsProperties();
    ConceptSource conceptSource =
        conceptService.getConceptSourceByUuid(
            conceptManagementAppsProperties.getSnomedCTConceptSourceUuidGlobalProperty(
                ConceptManagementAppsConstants.SNOMED_CT_CONCEPT_SOURCE_UUID_GP));

    if (StringUtils.equals(updateBy, "conceptUpdate")) {

      Collection<ConceptMap> mappings =
          conceptService.getConcept(Integer.parseInt(conceptId)).getConceptMappings();

      for (ConceptMap conceptMap : mappings) {

        if (StringUtils.equals(
                conceptMap.getConceptReferenceTerm().getConceptSource().getUuid(),
                conceptSource.getUuid())
            && StringUtils.equals(
                conceptMap.getConceptMapType().getUuid(),
                ConceptManagementAppsConstants.SAME_AS_CONCEPT_MAP_TYPE_UUID)) {
          termId =
              Integer.toString(conceptMap.getConceptReferenceTerm().getConceptReferenceTermId());
        }
      }
      return getRefTermAncestors(context, termId, locale, conceptSource);
    } else {
      return getRefTermAncestors(context, termId, locale, conceptSource);
    }
  }
  public void controller(
      FragmentConfiguration config,
      @SpringBean("emrApiProperties") EmrApiProperties emrApiProperties,
      @SpringBean("coreAppsProperties") CoreAppsProperties coreAppsProperties,
      @SpringBean("baseIdentifierSourceService") IdentifierSourceService identifierSourceService,
      @FragmentParam(required = false, value = "appContextModel") AppContextModel appContextModel,
      @FragmentParam("patient") Object patient,
      @InjectBeans PatientDomainWrapper wrapper,
      @SpringBean("conceptService") ConceptService conceptService,
      @SpringBean("obsService") ObsService obsService,
      @SpringBean("locationService") LocationService locationService,
      @SpringBean("appFrameworkService") AppFrameworkService appFrameworkService,
      @SpringBean("adtService") AdtService adtService,
      UiSessionContext sessionContext,
      UiUtils uiUtils,
      FragmentModel model) {

    if (patient instanceof Patient) {
      wrapper.setPatient((Patient) patient);
    } else {
      wrapper = (PatientDomainWrapper) patient;
    }
    config.addAttribute("patient", wrapper);
    config.addAttribute("patientNames", getNames(wrapper.getPersonName()));

    if (appContextModel == null) {
      AppContextModel contextModel = sessionContext.generateAppContextModel();
      contextModel.put("patient", new PatientContextModel(wrapper.getPatient()));
      model.addAttribute("appContextModel", contextModel);
    }

    List<Extension> firstLineFragments =
        appFrameworkService.getExtensionsForCurrentUser("patientHeader.firstLineFragments");
    Collections.sort(firstLineFragments);
    model.addAttribute("firstLineFragments", firstLineFragments);

    List<Extension> secondLineFragments =
        appFrameworkService.getExtensionsForCurrentUser("patientHeader.secondLineFragments");
    Collections.sort(secondLineFragments);
    model.addAttribute("secondLineFragments", secondLineFragments);

    // Adapting the header's content based on actual/current registration app's sections.
    List<AppDescriptor> regAppDescriptors = getRegistrationAppConfig(appFrameworkService);
    List<RegistrationSectionData> regAppSections =
        getRegistrationData(
            regAppDescriptors,
            new DataContextWrapper(
                sessionContext.getLocale(), wrapper, conceptService, obsService, locationService));
    config.addAttribute("regAppSections", regAppSections);

    List<ExtraPatientIdentifierType> extraPatientIdentifierTypes =
        new ArrayList<ExtraPatientIdentifierType>();

    for (PatientIdentifierType type : emrApiProperties.getExtraPatientIdentifierTypes()) {
      List<AutoGenerationOption> options = identifierSourceService.getAutoGenerationOptions(type);
      // TODO note that this may allow use to edit a identifier that should not be editable, or vice
      // versa, in the rare case where there are multiple autogeneration
      // TODO options for a single identifier type (which is possible if you have multiple
      // locations) and the manual entry boolean is different between those two generators
      extraPatientIdentifierTypes.add(
          new ExtraPatientIdentifierType(
              type, options.size() > 0 ? options.get(0).isManualEntryEnabled() : true));
    }

    config.addAttribute("extraPatientIdentifierTypes", extraPatientIdentifierTypes);
    config.addAttribute(
        "extraPatientIdentifiersMappedByType",
        wrapper.getExtraIdentifiersMappedByType(sessionContext.getSessionLocation()));
    config.addAttribute("dashboardUrl", coreAppsProperties.getDashboardUrl());
  }
  /**
   * @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;
  }