@Before
  public void setup() {

    emrApiProperties = mock(EmrApiProperties.class);
    paperRecordProperties = mock(PaperRecordProperties.class);
    adtService = mock(AdtService.class);
    messageSourceService = mock(MessageSourceService.class);
    addressHierarchyService = mock(AddressHierarchyService.class);

    when(emrApiProperties.getPrimaryIdentifierType()).thenReturn(primaryIdentifierType);
    when(paperRecordProperties.getPaperRecordIdentifierType())
        .thenReturn(paperRecordIdentifierType);
    when(adtService.getLocationThatSupportsVisits(argThat(any(Location.class))))
        .thenReturn(visitLocation);
    when(messageSourceService.getMessage("coreapps.gender.M", null, locale)).thenReturn("Masculin");
    when(messageSourceService.getMessage("coreapps.gender.F", null, locale)).thenReturn("FĂ©minin");

    setupAddressHierarchyLevels();

    wristbandTemplate.setAdtService(adtService);
    wristbandTemplate.setEmrApiProperties(emrApiProperties);
    wristbandTemplate.setMessageSourceService(messageSourceService);
    wristbandTemplate.setPaperRecordProperties(paperRecordProperties);
    wristbandTemplate.setAddressHierarchyService(addressHierarchyService);
  }
  @Override
  public void action(
      EncounterDomainWrapper encounterDomainWrapper,
      Obs dispositionObsGroupBeingCreated,
      Map<String, String[]> requestParameters) {

    if (encounterDomainWrapper.getVisit() == null) {
      return;
    }

    VisitDomainWrapper visitDomainWrapper = adtService.wrap(encounterDomainWrapper.getVisit());

    // if this is an active visit, we close it... *as long as* there are no subsequent encounters on
    // following days
    // (if there are subsequent encounters on following days, this is some sort of retrospective
    // entry, and we can't
    // determine exactly what should happen, so just do nothing)

    if (visitDomainWrapper.isActive()) {
      Date mostRecentEncounterDatetime =
          visitDomainWrapper.getMostRecentEncounter().getEncounterDatetime();

      if (!new DateMidnight(mostRecentEncounterDatetime)
          .isAfter(new DateMidnight(encounterDomainWrapper.getEncounterDatetime()))) {
        visitDomainWrapper.closeOnLastEncounterDatetime();
        visitService.saveVisit(visitDomainWrapper.getVisit());
      }
    }
  }
  @Override
  public boolean doStartTag(FormEntrySession session, PrintWriter out, Node parent, Node node)
      throws BadFormDesignException {

    List<Disposition> dispositions = null;

    VisitDomainWrapper visitDomainWrapper =
        session.getContext().getVisit() != null
            ? adtService.wrap((Visit) session.getContext().getVisit())
            : null;

    // TODO remove this feature toggle once awaiting admission is toggled one
    if (featureToggles.isFeatureEnabled("awaitingAdmission")) {
      if (visitDomainWrapper == null) {
        dispositions = dispositionService.getDispositions();
      } else {
        dispositions = dispositionService.getValidDispositions(visitDomainWrapper);
      }
    } else {
      dispositions = dispositionService.getDispositions();
    }

    Element dispositionObsGroup = node.getOwnerDocument().createElement("obsgroup");
    dispositionObsGroup.setAttribute(
        "groupingConceptId",
        emrApiProperties.getEmrApiConceptSource().getName()
            + ":"
            + EmrApiConstants.CONCEPT_CODE_DISPOSITION_CONCEPT_SET);

    // TODO: allow the label text to be overwritten, move the message code  to the coreapps module
    Element label = node.getOwnerDocument().createElement("label");
    Element uimessageLabel = node.getOwnerDocument().createElement("uimessage");
    uimessageLabel.setAttribute("code", "emr.consult.disposition");
    label.appendChild(uimessageLabel);
    dispositionObsGroup.appendChild(label);

    // TODO: allow the id to be passed in from the form?
    Element dispositionObs = node.getOwnerDocument().createElement("obs");
    dispositionObs.setAttribute("id", "disposition-" + UUID.randomUUID().toString());
    dispositionObs.setAttribute("style", "dropdown");
    dispositionObs.setAttribute(
        "conceptId",
        emrApiProperties.getEmrApiConceptSource().getName()
            + ":"
            + EmrApiConstants.CONCEPT_CODE_DISPOSITION);
    if (((Element) node).hasAttribute("required")
        && ((Element) node).getAttribute("required").equalsIgnoreCase("true")) {
      dispositionObs.setAttribute("required", "true");
    }

    // add the possible dispositions from the configured disposition retrieved from disposition
    // factory
    List<Control> controls = new ArrayList<Control>();

    String answerConceptIds = "";
    String answerCodes = "";
    Iterator<Disposition> i = dispositions.iterator();

    while (i.hasNext()) {
      Disposition disposition = i.next();

      answerConceptIds = answerConceptIds + disposition.getConceptCode() + (i.hasNext() ? "," : "");
      answerCodes = answerCodes + disposition.getName() + (i.hasNext() ? "," : "");

      // determine if there are any additional observations we need to collect for this disposition
      if (disposition.getAdditionalObs() != null && disposition.getAdditionalObs().size() > 0) {
        controls.add(buildNewControl(disposition, disposition.getAdditionalObs()));
      }
    }

    dispositionObs.setAttribute("answerConceptIds", answerConceptIds);
    dispositionObs.setAttribute("answerCodes", answerCodes);

    if (controls != null && controls.size() > 0) {
      generateControlsElement(dispositionObs, controls);
    }

    dispositionObsGroup.appendChild(dispositionObs);

    if (controls != null && controls.size() > 0) {
      generateAdditionalObsElements(dispositionObsGroup, controls);
    }

    node.appendChild(dispositionObsGroup);

    return true;
  }