/**
     *
     * Returns a section as a complete htmlform, including the three required encounter tags.
     *
     * @param htmlForm
     * @param sectionIndex
     * @return
     * @throws Exception
     */
    public static String getSectionAsFormXml(HtmlForm htmlForm, Integer sectionIndex) throws Exception{
        Document doc = HtmlFormEntryUtil.stringToDocument(htmlForm.getXmlData());
        NodeList nl = doc.getElementsByTagName("section");
        Node sectionNode = null;
        try {
            sectionNode = nl.item(sectionIndex);
        } catch (Exception ex){
            throw new RuntimeException("The section index that you've passed in is out of range.  There are only " + nl.getLength() + " section tags in the document and you requested section tag " + sectionIndex);
        }
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc2 = db.newDocument();
        Node formRoot = doc2.createElement("htmlform");
        doc2.appendChild(formRoot);
        formRoot.appendChild(doc2.importNode(sectionNode, true));
        if (doc2.getElementsByTagName("encounterLocation").getLength() == 0){
            Node encLoc = doc2.createElement("encounterLocation");
            formRoot.appendChild(encLoc);
        }
        if (doc2.getElementsByTagName("encounterDate").getLength() == 0){
            Node encDate = doc2.createElement("encounterDate");
            formRoot.appendChild(encDate);
        }
        if (doc2.getElementsByTagName("encounterProvider").getLength() == 0){
            Node encDate = doc2.createElement("encounterProvider");
            Element encDateElement = (Element) encDate;
            encDateElement.setAttribute("role","Provider");
            formRoot.appendChild(encDate);

        }
        doc2.normalize();

        try
        {
           DOMSource domSource = new DOMSource(doc2);
           StringWriter writer = new StringWriter();
           StreamResult result = new StreamResult(writer);
           TransformerFactory tf = TransformerFactory.newInstance();
           Transformer transformer = tf.newTransformer();
           transformer.transform(domSource, result);
           return writer.toString();
        }
        catch(TransformerException ex)
        {
           ex.printStackTrace();
           return null;
        }
    }
 /**
  * returns a Map<Integer, String> of all form sections, in order,
  * where the String value is either the specified name, or an arbitrary one if none was given.
  * and the integer is the numeric index of the sections, starting with 0.
  *
  * @param HtmlForm htmlForm
  * @return
  */
 public static Map<Integer, String> getSectionIndex(HtmlForm htmlForm) throws Exception{
     Document doc = HtmlFormEntryUtil.stringToDocument(htmlForm.getXmlData());
     FormEntrySession session = new FormEntrySession(HtmlFormEntryUtil.getFakePerson(), htmlForm, null); // session gets a null HttpSession
     NodeList nl = doc.getElementsByTagName("section");
     Map<Integer, String> ret = new LinkedHashMap<Integer, String>();
     for (int i = 0; i < nl.getLength(); i++){
         Node sectionNode = nl.item(i);
         NamedNodeMap map = sectionNode.getAttributes();
         String headerLabel = "no name specified";
         for (int j = 0; j < map.getLength(); ++j) {
             Node attribute = map.item(j);
             if (attribute.getNodeName().equals("headerLabel")) {
                 headerLabel = attribute.getNodeValue();
             }
             if (attribute.getNodeName().equals("headerCode")) {
                 Translator trans = session.getContext().getTranslator();
                 headerLabel = trans.translate(Context.getLocale().toString(), attribute.getNodeValue());
             }
         }
         ret.put(i, headerLabel);
     }
     return ret;
 }
  public void controller(
      @RequestParam(value = "patientId", required = false) Patient patient,
      @RequestParam(value = "headerForm") String headerForm,
      @RequestParam(value = "flowsheets") String[] flowsheets,
      @RequestParam(value = "viewOnly", required = false) Boolean viewOnly,
      @RequestParam(value = "requireEncounter", required = false) Boolean requireEncounter,
      UiUtils ui,
      PageModel model,
      @SpringBean("htmlFormEntryService") HtmlFormEntryService htmlFormEntryService,
      @SpringBean("formService") FormService formService,
      @SpringBean("locationService") LocationService locationService,
      @SpringBean("coreResourceFactory") ResourceFactory resourceFactory,
      @InjectBeans PatientDomainWrapper patientDomainWrapper,
      PageRequest pageRequest) {

    patientDomainWrapper.setPatient(patient);
    model.addAttribute("patient", patientDomainWrapper);
    model.addAttribute("headerForm", headerForm);
    model.addAttribute("flowsheets", flowsheets);
    model.addAttribute("requireEncounter", (requireEncounter == null || requireEncounter));

    Location defaultLocation = null;
    Integer locationId =
        pageRequest
            .getSession()
            .getAttribute(PihMalawiWebConstants.SESSION_LOCATION_ID, Integer.TYPE);
    if (locationId != null) {
      defaultLocation = locationService.getLocation(locationId);
    }

    List<Encounter> allEncounters = new ArrayList<Encounter>();

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

    String headerFormResource = "pihmalawi:htmlforms/" + headerForm + ".xml";

    HtmlForm headerHtmlForm =
        getHtmlFormFromResource(
            headerFormResource, resourceFactory, formService, htmlFormEntryService);
    model.addAttribute("headerForm", headerForm);

    Encounter headerEncounter = null;
    List<Encounter> headerEncounters = getEncountersForForm(patient, headerHtmlForm);
    if (headerEncounters.size() > 0) {
      headerEncounter = headerEncounters.get(headerEncounters.size() - 1); // Most recent
      if (headerEncounters.size() > 1) {
        alerts.add(
            "WARNING:  More than one "
                + headerHtmlForm.getName()
                + " encounters exist for this patient.  Displaying the most recent only.");
      }
      allEncounters.add(headerEncounter);
    }
    model.addAttribute("headerEncounter", headerEncounter);

    Map<String, HtmlForm> flowsheetForms = new LinkedHashMap<String, HtmlForm>();
    Map<String, List<Integer>> flowsheetEncounters = new LinkedHashMap<String, List<Integer>>();
    if (flowsheets != null) {
      for (String flowsheet : flowsheets) {
        String flowsheetResource = "pihmalawi:htmlforms/" + flowsheet + ".xml";
        HtmlForm htmlForm =
            getHtmlFormFromResource(
                flowsheetResource, resourceFactory, formService, htmlFormEntryService);
        flowsheetForms.put(flowsheet, htmlForm);
        List<Integer> encIds = new ArrayList<Integer>();
        List<Encounter> encounters = getEncountersForForm(patient, htmlForm);
        for (Encounter e : encounters) {
          encIds.add(e.getEncounterId());
          allEncounters.add(e);
        }
        flowsheetEncounters.put(flowsheet, encIds);
      }
    }
    model.addAttribute("flowsheetForms", flowsheetForms);
    model.addAttribute("flowsheetEncounters", flowsheetEncounters);

    model.addAttribute("alerts", alerts);

    if (defaultLocation == null) {
      Date maxDate = null;
      if (allEncounters.size() > 0) {
        for (Encounter e : allEncounters) {
          if (maxDate == null || maxDate.compareTo(e.getEncounterDatetime()) < 0) {
            maxDate = e.getEncounterDatetime();
            defaultLocation = e.getLocation();
          }
        }
      }
    }
    model.addAttribute(
        "defaultLocationId", defaultLocation == null ? null : defaultLocation.getLocationId());
    model.addAttribute("viewOnly", viewOnly == Boolean.TRUE);

    model.addAttribute(
        "returnUrl",
        ui.pageLink(
            "pihmalawi",
            "mastercard",
            SimpleObject.create(
                "patientId",
                patient.getId(),
                "headerForm",
                headerForm,
                "flowsheets",
                flowsheets,
                "viewOnly",
                viewOnly)));
  }
 /**
  * @return all encounters for the given patient that have the same encounter type as the given
  *     form
  */
 protected List<Encounter> getEncountersForForm(Patient p, HtmlForm form) {
   EncountersForPatientDataDefinition edd = new EncountersForPatientDataDefinition();
   edd.addType(form.getForm().getEncounterType());
   List<Encounter> ret = DataUtil.evaluateForPatient(edd, p.getPatientId(), List.class);
   return ret == null ? new ArrayList<Encounter>() : ret;
 }