Package org.openmrs.module.htmlformentry.export

Source Code of org.openmrs.module.htmlformentry.export.HtmlFormEntryExportUtil

package org.openmrs.module.htmlformentry.export;

import java.io.StringWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.Concept;
import org.openmrs.Encounter;
import org.openmrs.Obs;
import org.openmrs.PatientIdentifierType;
import org.openmrs.api.context.Context;
import org.openmrs.module.htmlformentry.FormEntryContext;
import org.openmrs.module.htmlformentry.FormEntryContext.Mode;
import org.openmrs.module.htmlformentry.FormEntrySession;
import org.openmrs.module.htmlformentry.FormSubmissionController;
import org.openmrs.module.htmlformentry.HtmlForm;
import org.openmrs.module.htmlformentry.HtmlFormEntryUtil;
import org.openmrs.module.htmlformentry.Translator;
import org.openmrs.module.htmlformentry.action.FormSubmissionControllerAction;
import org.openmrs.module.htmlformentry.element.ObsSubmissionElement;
import org.openmrs.module.htmlformentry.schema.HtmlFormField;
import org.openmrs.module.htmlformentry.schema.HtmlFormSchema;
import org.openmrs.module.htmlformentry.schema.ObsField;
import org.openmrs.module.htmlformentry.schema.ObsGroup;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class HtmlFormEntryExportUtil {
   
    protected final static Log log = LogFactory.getLog(HtmlFormEntryExportUtil.class);
   
    private static DateFormat DATE_FORMATTER = new SimpleDateFormat("dd-MMM-yyyy");
   
    private static final String DEFAULT_QUOTE = "\"";

    private static final String DEFAULT_COLUMN_SEPARATOR = ",";

    private static final String DEFAULT_LINE_SEPARATOR = "\n";
   
    private static final String EMPTY = "";
   
    /**
     * 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;
    }
   
    /**
     *
     * 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 the encounter with the obs that aren't used when populating form are removed. 
     * This *doesn't* save the encounter.
     * TODO: handle Orders?
     *
     * @param e
     * @param htmlform
     * @return
     * @throws Exception
     */
    public static Encounter trimEncounterToMatchForm(Encounter e, HtmlForm htmlform) throws Exception {
       
       //this should move existing obs from session to tag handlers.
        FormEntrySession session = new FormEntrySession(e.getPatient(), e, FormEntryContext.Mode.VIEW, htmlform, null); // session gets a null HttpSession
        session.getHtmlToDisplay();
       
        if (log.isDebugEnabled()){
            Map<Concept, List<Obs>>  map = session.getContext().getExistingObs();
            if (map != null){
                for (Map.Entry<Concept, List<Obs>> existingObs : map.entrySet()){
                    List<Obs> oList = existingObs.getValue();
                    for (Obs oInner : oList)
                        log.debug("Obs in existingObs " + existingObs.getKey() + " " + oInner.getConcept());
                }
            }
            Map<Obs, Set<Obs>> map2 = session.getContext().getExistingObsInGroups();
            if (map2 != null){
                for (Map.Entry<Obs, Set<Obs>> existingObsInGroups : map2.entrySet()){
                    Set<Obs> oList = existingObsInGroups.getValue();
                    for (Obs oInner : oList)
                        log.debug("Obs in existingObsInGroups " + existingObsInGroups.getKey().getConcept() + " " + oInner.getConcept());
                }
            }
        }
        Encounter ret = new Encounter();
        ret.setCreator(e.getCreator());
        ret.setEncounterDatetime(e.getEncounterDatetime());
        ret.setProvider(e.getProvider());
        ret.setLocation(e.getLocation());
        ret.setDateCreated(e.getDateCreated());
        ret.setPatient(e.getPatient());
        //renders new encounter unsave-able:
        ret.setEncounterId(e.getEncounterId());
       
        for (Obs oTest : e.getAllObs()){
            boolean found = false;
            if (session.getContext().getExistingObs() != null && !oTest.isObsGrouping()){
                List<Obs> obsList = session.getContext().getExistingObs().get(oTest.getConcept());
                if (obsList != null && obsList.size() > 0){
                    for (Obs o : obsList){
                        if (o.getObsId().equals(oTest.getObsId())){
                            found = true;
                            continue;
                        }
                    }  
                }
            }
            if (!found && session.getContext().getExistingObsInGroups() != null){
                for (Map.Entry<Obs, Set<Obs>> mapEntry : session.getContext().getExistingObsInGroups().entrySet()){
                    if (mapEntry.getKey().equals(oTest)){
                        found = true;
                        continue;
                    } else {
                        Set<Obs> oSet = mapEntry.getValue();
                        //note: oSet.contains fails for some reason
                        for (Obs o:oSet){
                              if (o.getObsId().equals(oTest.getObsId())){
                                  found = true;
                                  continue;
                              }   
                        } 
                    }
                }
            }
            if (!found)
                ret.addObs(oTest);
        }
        session = null;
        return ret;
   
   
    /**
     *
     * Generate the header row for the csv file.
     *
     * @param form
     * @param extraCols
     * @return
     * @throws Exception
     */
    public static String generateColumnHeadersFromHtmlForm(HtmlForm form, List<String> extraCols, StringBuffer sb, List<PatientIdentifierType> pitList) throws Exception {
        FormEntrySession session = new FormEntrySession(HtmlFormEntryUtil.getFakePerson(), form, null); // session gets a null HttpSession
        session.getHtmlToDisplay();
        HtmlFormSchema hfs = session.getContext().getSchema();
       
        sb.
        append(DEFAULT_QUOTE).append("ENCOUNTER_ID").append(DEFAULT_QUOTE).append(DEFAULT_COLUMN_SEPARATOR).
        append(DEFAULT_QUOTE).append("ENCOUNTER_DATE").append(DEFAULT_QUOTE).append(DEFAULT_COLUMN_SEPARATOR).
        append(DEFAULT_QUOTE).append("ENCOUNTER_LOCATION").append(DEFAULT_QUOTE).append(DEFAULT_COLUMN_SEPARATOR).
        append(DEFAULT_QUOTE).append("ENCOUNTER_PROVIDER").append(DEFAULT_QUOTE).append(DEFAULT_COLUMN_SEPARATOR).
        append(DEFAULT_QUOTE).append("INTERNAL_PATIENT_ID").append(DEFAULT_QUOTE).append(DEFAULT_COLUMN_SEPARATOR);
        int index = 1;
        for (PatientIdentifierType pit :  pitList){
            sb.append(DEFAULT_QUOTE).append(pit.getName()).append(DEFAULT_QUOTE);
            if (index < pitList.size())
                sb.append(DEFAULT_COLUMN_SEPARATOR);
            index ++;
        }   
       
        for (HtmlFormField hfsec : hfs.getAllFields())
                sb = generateColumnHeadersFromHtmlFormHelper(hfsec, extraCols, sb);

        session = null;
        sb.append(DEFAULT_LINE_SEPARATOR);
        return sb.toString();
    }
   
    private static StringBuffer generateColumnHeadersFromHtmlFormHelper(HtmlFormField hff, List<String> extraCols, StringBuffer sb){
        if (hff instanceof ObsField){
            ObsField of = (ObsField) hff;     
            sb = buildHeadersForObsField(of, extraCols, sb);
        } else if (hff instanceof ObsGroup){
                ObsGroup og = (ObsGroup) hff;
                for (HtmlFormField of : og.getChildren()){
                    sb = generateColumnHeadersFromHtmlFormHelper(of, extraCols, sb);
                }
        }
        return sb;
    }
   
    /**
     *
     * Builds the root column name for the concept from the conceptID
     *
     * @param of
     * @return
     */
    private static String buildColumnHeader(ObsField of){
        StringBuilder sb = new StringBuilder(EMPTY);
        Locale loc = Context.getLocale();
        if (of.getQuestion() != null){
            //TODO: add fieldId, fieldPart, Page???
            sb.append(of.getQuestion().getBestShortName(loc));
        } else if (of.getAnswers().size() == 1){
            sb.append(of.getAnswers().get(0).getConcept().getBestShortName(loc));
        } else {
            throw new RuntimeException("Obs Field has no conceptId, and multiple answers -- this isn't yet supported.");
        }
        return sb.toString().replaceAll("\\s", "_").replaceAll("-", "_").toUpperCase();
    }
   
    /**
     *
     * Adds all of the columns for an Obs Field.
     *
     * @param of
     * @param extraCols
     * @param sb
     * @return
     */
    private static StringBuffer buildHeadersForObsField(ObsField of, List<String> extraCols, StringBuffer sb){
       
        sb.append(DEFAULT_COLUMN_SEPARATOR);
        sb.append(DEFAULT_QUOTE);
        String columnHeader = buildColumnHeader(of);
        sb.append(columnHeader);
        sb.append(DEFAULT_QUOTE);
   
        sb.append(DEFAULT_COLUMN_SEPARATOR);
        sb.append(DEFAULT_QUOTE);    
        sb.append(columnHeader + "_DATE");
        sb.append(DEFAULT_QUOTE);
       
      //always export obsGroupId
        sb.append(DEFAULT_COLUMN_SEPARATOR);
        sb.append(DEFAULT_QUOTE);    
        sb.append(columnHeader + "_PARENT");
        sb.append(DEFAULT_QUOTE);
       
        if (extraCols != null){
            for (String st : extraCols){
                if (st.equals("valueModifier")){
                    sb.append(DEFAULT_COLUMN_SEPARATOR);
                    sb.append(DEFAULT_QUOTE);       
                    sb.append(columnHeader + "_VALUE_MOD");                                  
                    sb.append(DEFAULT_QUOTE);
                } else if (st.equals("accessionNumber")){
                    sb.append(DEFAULT_COLUMN_SEPARATOR);
                    sb.append(DEFAULT_QUOTE);       
                    sb.append(columnHeader + "_ACCESSION_NUM");                                  
                    sb.append(DEFAULT_QUOTE);
                } else if (st.equals("comment")){
                    sb.append(DEFAULT_COLUMN_SEPARATOR);
                    sb.append(DEFAULT_QUOTE);       
                    sb.append(columnHeader + "_COMMENT");                                  
                    sb.append(DEFAULT_QUOTE);
                }
            }
        }
       
        return sb;
    }
   
    /**
     *
     * Generates all of the data rows
     *
     * @param form
     * @param extraCols
     * @param sb
     * @return
     * @throws Exception
     */
    public static String generateColumnDataFromHtmlForm(List<Encounter> encounters, HtmlForm form, List<String> extraCols, StringBuffer sb, Locale locale,List<PatientIdentifierType> pitList) throws Exception {
        for (Encounter e: encounters){
           
            sb.append(DEFAULT_QUOTE).append(e.getEncounterId()).append(DEFAULT_QUOTE).append(DEFAULT_COLUMN_SEPARATOR);        
            sb.append(DEFAULT_QUOTE).append(DATE_FORMATTER.format(e.getEncounterDatetime())).append(DEFAULT_QUOTE).append(DEFAULT_COLUMN_SEPARATOR);
            sb.append(DEFAULT_QUOTE).append(e.getLocation().getName()).append(DEFAULT_QUOTE).append(DEFAULT_COLUMN_SEPARATOR);
            sb.append(DEFAULT_QUOTE).append(e.getProvider().getGivenName()+ " " + e.getProvider().getFamilyName()).append(DEFAULT_QUOTE).append(DEFAULT_COLUMN_SEPARATOR);
            sb.append(DEFAULT_QUOTE).append((e.getPatient() != null ? e.getPatient().getPatientId() : EMPTY)).append(DEFAULT_QUOTE).append(DEFAULT_COLUMN_SEPARATOR);      
            int index = 1;
            for (PatientIdentifierType pit :  pitList){
                sb.append(DEFAULT_QUOTE).append(e.getPatient().getPatientIdentifier(pit)).append(DEFAULT_QUOTE);
                if (index < pitList.size())
                    sb.append(DEFAULT_COLUMN_SEPARATOR);
                index ++;
            }
           
            FormEntrySession session = new FormEntrySession(e.getPatient(), e, Mode.VIEW, form, null); // session doesn't get HttpSession
            session.getHtmlToDisplay();
            FormSubmissionController  fsa = session.getSubmissionController();
            List<FormSubmissionControllerAction> actions = fsa.getActions();
            for (FormSubmissionControllerAction fsca : actions){
                if (fsca instanceof ObsSubmissionElement){
                    ObsSubmissionElement ose = (ObsSubmissionElement) fsca;
                    sb = appendObsToRow(ose, sb, extraCols, locale);  
                } else {
                    //TODO: add programs, orders, logic, etc...
                    // just make sure these are in the headers too...
                }
            }
            session = null;
            sb.append(DEFAULT_LINE_SEPARATOR);
        }
        return sb.toString();
    }
   
    /**
     *
     * Writes the row entries for the Obs
     *
     * @param o
     * @param sb
     * @param extraCols
     * @param rowStarted
     * @return
     */
    private static StringBuffer appendObsToRow(ObsSubmissionElement ose, StringBuffer sb, List<String> extraCols, Locale locale){
            Obs o = ose.getExistingObs();      

            sb.append(DEFAULT_COLUMN_SEPARATOR);
            sb.append(DEFAULT_QUOTE);
            if (ose.getConcept() != null)
                sb.append((o != null) ? getObsValueAsString(Context.getLocale(), o):EMPTY);
            else
                sb.append((o != null) ? o.getConcept().getBestName(locale):EMPTY);
            sb.append(DEFAULT_QUOTE);
           
            sb.append(DEFAULT_COLUMN_SEPARATOR);
            sb.append(DEFAULT_QUOTE);    
            sb.append((o!=null)? Context.getDateFormat().format(o.getObsDatetime()):EMPTY);                                  
            sb.append(DEFAULT_QUOTE);
           
            sb.append(DEFAULT_COLUMN_SEPARATOR);
            sb.append(DEFAULT_QUOTE);    
            sb.append(getObsGroupPath(o));                                  
            sb.append(DEFAULT_QUOTE);
           
            if (extraCols != null){
                for (String st : extraCols){
                    if (st.equals("valueModifier")){
                        sb.append(DEFAULT_COLUMN_SEPARATOR);
                        sb.append(DEFAULT_QUOTE);       
                        sb.append((o != null && o.getValueModifier() != null) ? o.getValueModifier():EMPTY);                                  
                        sb.append(DEFAULT_QUOTE);
                    } else if (st.equals("accessionNumber")){
                        sb.append(DEFAULT_COLUMN_SEPARATOR);
                        sb.append(DEFAULT_QUOTE);       
                        sb.append((o != null && o.getAccessionNumber() != null) ? o.getAccessionNumber():EMPTY);                                  
                        sb.append(DEFAULT_QUOTE);
                    } else if (st.equals("comment")){
                        sb.append(DEFAULT_COLUMN_SEPARATOR);
                        sb.append(DEFAULT_QUOTE);       
                        sb.append((o != null && o.getComment() != null) ? o.getComment():EMPTY);                                  
                        sb.append(DEFAULT_QUOTE);
                    }
                }
            }
        return sb;
    }
   
    public static String getObsGroupPath(Obs o){
        StringBuilder st = new StringBuilder(EMPTY);
        if (o != null)
            while (o.getObsGroup() != null){
                o = o.getObsGroup();
                st.insert(0, o.getObsId() + "|");
            }
        return st.toString();
    }
   
    /**
     * The main method for exporting an htmlform to a csv.
     *
     * @param encounters
     * @param form
     * @param extraCols
     * @param sb
     * @param locale
     * @param pitList
     * @return the complete StringBuffer, ready for export
     */
    public static StringBuffer buildHtmlFormExport(List<Encounter> encounters, HtmlForm htmlForm, List<String> extraCols, StringBuffer sb, Locale locale,List<PatientIdentifierType> pitList){
        try {
            HtmlFormEntryExportUtil.generateColumnHeadersFromHtmlForm(htmlForm, extraCols, sb, pitList);
            HtmlFormEntryExportUtil.generateColumnDataFromHtmlForm(encounters, htmlForm, extraCols, sb, Context.getLocale(), pitList);
        } catch (Exception ex){
            ex.printStackTrace();
            throw new RuntimeException("Unable to export form.  Check the log for details.  Underlying error was: " + ex.getMessage());
        }
        return sb;
    }
   
    /**
     *
     * format the obs value
     *
     * @param locale
     * @param o
     * @return
     */
    public static String getObsValueAsString(Locale locale, Obs o){
        String ret = "";
        if (o.getConcept() != null){
            String abbrev = o.getConcept().getDatatype().getHl7Abbreviation();
            if (abbrev.equals("DT")){
                return (o.getValueDatetime() == null ? "" : Context.getDateFormat().format(o.getValueDatetime()));
            } else if (abbrev.equals("TS") && o.getValueDatetime() != null){
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                return sdf.format(o.getValueDatetime());
            } else {
                ret = o.getValueAsString(locale);
            }   
        }
        return ret;
    }
   
}
TOP

Related Classes of org.openmrs.module.htmlformentry.export.HtmlFormEntryExportUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.