package ke.go.moh.oec.pisinterfaces.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import ke.go.moh.oec.pisinterfaces.beans.CdaRecord;
import org.apache.commons.codec.binary.Base64;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Parse CDAs and meta-data from XML documents returned from the external
* service used to query for CDAs.
*
* Expected format:
* <query_response>
* <record>
* <cda_id>[integer]</cda_id>
* <cda>[base 64 encoded CDA]</cda>
* </record>
* </query_response>
*
*/
public class CdaQueryResult {
Map<String, String> cdaList = new HashMap<String, String>();
Map<String, CdaRecord> recordList = new HashMap<String, CdaRecord>();
/**
* SAX parser implementation used to parse a document returned from the
* external CDA query service, defining the bulk of the available row data
* for any matching CDAs.
*
* @param document the result document from a query request
* @return a map of {cda_id: CdaRecord} for each cda found in the doc.
*/
public Map<String, CdaRecord> parseDocument(InputStream document) throws SiteException {
SAXParserFactory spf = SAXParserFactory.newInstance();
try {
SAXParser saxParser = spf.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
String elementInProcess;
String cda_id = null;
StringBuffer cda_buffer = new StringBuffer();
CdaRecord record;
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase("record")) {
record = new CdaRecord();
}
else {
elementInProcess = new String(qName);
}
}
public void endElement(String uri, String localName,
String qName) throws SAXException {
if (qName.equalsIgnoreCase("record")) {
// End of record - push decoded results
// The CDA itself is base 64 encrypted by the query
// service, to avoid any nested CDATA decoding trouble.
byte[] decodedBytes = Base64.decodeBase64(cda_buffer.toString());
record.setCDA(new String(decodedBytes));
CdaQueryResult.this.recordList.put(cda_id, record);
// Reset state for next record
cda_id = null;
cda_buffer.setLength(0);
elementInProcess = null;
}
}
public void characters(char ch[], int start, int length) throws SAXException {
String value = new String(ch, start, length);
if ("cda_id".equals(elementInProcess)) {
assert (record.getCdaID() == null); // catch need to accumulate
cda_id = value;
record.setCdaID(value);
} else if ("first_name".equals(elementInProcess)) {
assert (record.getFirstName() == null); // catch need to accumulate
record.setFirstName(value);
} else if ("last_name".equals(elementInProcess)) {
assert (record.getLastName() == null); // catch need to accumulate
record.setLastName(value);
} else if ("patient_clinical_id".equals(elementInProcess)) {
assert (record.getClinicId() == null); // catch need to accumulate
record.setClinicId(value);
} else if ("hdss_id".equals(elementInProcess)) {
assert (record.getHdssId() == null); // catch need to accumulate
record.setHdssId(value);
} else if ("source_system".equals(elementInProcess)) {
assert (record.getSourceSystem() == null); // catch need to accumulate
record.setSourceSystem(value);
} else if ("cda_dob".equals(elementInProcess)) {
assert (record.getCdaDOB() == null); // catch need to accumulate
record.setCdaDOB(value);
} else if ("gender".equals(elementInProcess)) {
assert (record.getGender() == null); // catch need to accumulate
record.setGender(value);
} else if ("date_generated".equals(elementInProcess)) {
assert (record.getDateGenerated() == null); // catch need to accumulate
record.setDateGenerated(value);
} else if ("cda".equals(elementInProcess)) {
// Frequently breaks over many lines; accumulate.
cda_buffer.append(ch, start, length);
} else {
Logger.getLogger(CdaQueryResult.class.getName()).
severe("unexpected XML entity: " + elementInProcess);
}
}
};
saxParser.parse(document, handler);
} catch (Exception e) {
throw new SiteException("Unable to parse response CDA(s)", e);
}
return recordList;
}
}