Skip to content
Browse files

Merge pull request #63 from pbugni/master

CDA query channel and web app mods for multiple CDA results
  • Loading branch information...
2 parents 5038531 + 679055d commit 1eb38a0751c1ab49eabf8bccb86b0128dbf2d804 @Pcb Pcb committed Mar 26, 2012
View
12 cds/database/add_CDA_name_n_date_cols.sql
@@ -0,0 +1,12 @@
+-- Additional fields for index and retrieval of CDS records
+--
+-- to run, from a command shell:
+-- mysql -u <user> -p <database_name> < <this_file>
+--
+-- i.e.
+-- mysql -u oecuser -p cds < add_CDA_name_n_date_cols.sql
+
+ALTER TABLE CDA ADD COLUMN first_name TEXT NULL;
+ALTER TABLE CDA ADD COLUMN last_name TEXT NULL;
+ALTER TABLE CDA ADD COLUMN date_generated DATETIME NOT NULL;
+ALTER TABLE CDA ADD COLUMN date_stored DATETIME NOT NULL;
View
62 oec2Interface/mirth/CDA query.xml
@@ -7,22 +7,34 @@ Queries should be HTTP POSTed to this channel in XML format, using the &apos;que
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
&lt;patientIdentification&gt;
+ &lt;cda_id/&gt;
&lt;identification&gt;123abc&lt;/identification&gt;
&lt;identificationType&gt;HDSS&lt;/identificationType&gt;
&lt;requestSource&gt;EMR&lt;/requestSource&gt;
&lt;/patientIdentification&gt;
-(Only the &lt;identification/&gt; element is considered in the query.)
+(Only the &lt;cda_id/&gt; element is considered in the query if defined. Fall back to &lt;identification/&gt; if not.)
+
+For each matching document found, they will be a &lt;record/&gt; element returned associated with their respective cda_id values in an XML document of the following structure:
+
+&lt;query_response&gt;
+ &lt;record&gt;
+ &lt;cda_id&gt;20&lt;/cda_id&gt;
+ &lt;cda&gt;[base 64 encoded CDA]&lt;/cda&gt;
+ &lt;/record&gt;
+&lt;/query_response&gt;
+
+(The CDA itself is base 64 encoded to work around any nested CDATA decryption problems.)
To configure the cds database name, host, port, user &amp; password, alter the connection string at the top of the one destination in this channel.
</description>
<enabled>true</enabled>
<version>2.1.1.5490</version>
<lastModified>
- <time>1331242226956</time>
+ <time>1332460210705</time>
<timezone>America/Los_Angeles</timezone>
</lastModified>
- <revision>75</revision>
+ <revision>102</revision>
<sourceConnector>
<name>sourceConnector</name>
<properties>
@@ -41,13 +53,15 @@ To configure the cds database name, host, port, user &amp; password, alter the c
<name>decode query XML</name>
<script>var query = new XML(Packages.java.net.URLDecoder.decode(msg[&apos;Parameters&apos;][&apos;query&apos;].toString()));
+channelMap.put(&apos;cda_id&apos;, query[&apos;cdaID&apos;]);
channelMap.put(&apos;id&apos;, query[&apos;identification&apos;]);</script>
<type>JavaScript</type>
<data class="map">
<entry>
<string>Script</string>
<string>var query = new XML(Packages.java.net.URLDecoder.decode(msg[&apos;Parameters&apos;][&apos;query&apos;].toString()));
+channelMap.put(&apos;cda_id&apos;, query[&apos;cdaID&apos;]);
channelMap.put(&apos;id&apos;, query[&apos;identification&apos;]);</string>
</entry>
</data>
@@ -132,26 +146,52 @@ return false;</script>
<property name="password">yourPassword</property>
<property name="query"></property>
<property name="script">// The cds database name, host, port, user &amp; password must be correctly configured in the following connection line:
-var dbConn = DatabaseConnectionFactory.createDatabaseConnection(&apos;com.mysql.jdbc.Driver&apos;,&apos;jdbc:mysql://localhost/cds&apos;,&apos;oecuser&apos;,&apos;yourPassword&apos;);
+var dbConn = DatabaseConnectionFactory.createDatabaseConnection(&apos;com.mysql.jdbc.Driver&apos;,
+ &apos;jdbc:mysql://localhost/cds&apos;,
+ &apos;oecuser&apos;,
+ &apos;yourPassword&apos;);
+var cda_id = channelMap.get(&apos;cda_id&apos;);
+var id = channelMap.get(&apos;id&apos;);
+
+var column = null;
+var value = null;
+
+// We query by one column, preferring the unique cda_id (ignoring the other if set)
+if (typeof cda_id != undefined &amp;&amp; cda_id.toString().length &gt; 0) {
+ column = &apos;cda_id&apos;;
+ value = cda_id.toString();
+} else if (typeof id != undefined &amp;&amp; id.toString().length &gt; 0) {
+ column = &apos;patient_clinical_id&apos;;
+ value = id.toString();
+} else {
+ var response = ResponseFactory.getFailureResponse(&quot;Either &lt;cda_id/&gt; or &lt;identification/&gt; must be defined&quot;);
+ responseMap.put(&quot;httpResponse&quot;, response);
+ return;
+}
-var qs = &quot;SELECT cda FROM CDA WHERE patient_clinical_id = ?&quot;;
+var qs = &quot;SELECT cda_id, cda FROM CDA WHERE &quot; + column + &quot; = ?&quot;;
var params = java.util.ArrayList()
-params.add(channelMap.get(&apos;id&apos;).toString());
+params.add(value);
result = dbConn.executeCachedQuery(qs, params);
-// If no match is found, return the empty string
-// Multiple matches will result in concatinated CDAs
-var cda = &apos;&apos;;
+// Return zero or more matching CDAs in an xml doc.
+var doc = &lt;query_response/&gt;;
while(result.next()) {
- cda += result.getString(1);
+ var record = &lt;record/&gt;;
+ record.cda_id = result.getInt(1);
+ record.cda = FileUtil.encode(result.getString(2).getBytes());
+ doc.appendChild(record);
}
+// This *should* provide the XML declaration, but it doesn&apos;t: doc = new XML(doc);
+// Add it by hand:
+doc = &apos;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot; ?&gt;&apos; + doc.toString()
dbConn.close();
// This stores an HTTP 200 (success) with the body &apos;cda&apos; as
// set above in the response variable &quot;httpResponse&quot;, which
// should be selected as the &quot;Respond From&quot; variable on the source
// tab.
-var response = ResponseFactory.getSuccessResponse(cda);
+var response = ResponseFactory.getSuccessResponse(doc);
responseMap.put(&quot;httpResponse&quot;, response);
View
13 oec2Interface/pom.xml
@@ -39,7 +39,11 @@
<artifactId>spring-webflow</artifactId>
<version>1.0.6</version>
</dependency>
-
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ <version>1.2</version>
+ </dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>servlet-api</artifactId>
@@ -55,7 +59,12 @@
<artifactId>jsr311-api</artifactId>
<version>1.0</version>
</dependency>
- </dependencies>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.4</version>
+ </dependency>
+ </dependencies>
<build>
<finalName>oec2.interface</finalName>
<plugins>
View
17 oec2Interface/src/main/java/ke/go/moh/oec/pisinterfaces/beans/PatientIdentification.java
@@ -15,11 +15,26 @@
*/
@XmlRootElement
public class PatientIdentification {
+ private String cdaID;
private String identification;
private String identificationType;
private String requestSource;
- /**
+ /**
+ * @return the cdaID, the database unique identification
+ */
+ public String getCdaID() {
+ return cdaID;
+ }
+
+ /**
+ * @param cdaID the database unique identification
+ */
+ public void setCdaID(String cdaID) {
+ this.cdaID = cdaID;
+ }
+
+ /**
* @return the identification
*/
public String getIdentification() {
View
351 ...nterface/src/main/java/ke/go/moh/oec/pisinterfaces/controller/CdaInterfaceController.java
@@ -1,161 +1,234 @@
package ke.go.moh.oec.pisinterfaces.controller;
-import java.io.BufferedReader;
+import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
-
+import java.util.logging.Level;
+import java.util.logging.Logger;
import ke.go.moh.oec.pisinterfaces.beans.PatientIdentification;
+import ke.go.moh.oec.pisinterfaces.util.CdaQueryResult;
import ke.go.moh.oec.pisinterfaces.util.JavaToXML;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.SessionAttributes;
+import org.springframework.web.bind.annotation.*;
/**
- *
+ *
* @author Fiston
- *
- * The controller that controls all requests used by this interface.
- *
+ *
+ * The controller that controls all requests used by this interface.
+ *
+ * In order to handle ReSTful URLs (such as "/viewCda/{cdaID}"), it is necessary
+ * to serve from a non-root context. See the web.xml file for path info.
+ *
*/
@Controller
-@RequestMapping("/*.htm")
-@SessionAttributes("patientId")
+@SessionAttributes({"patientId", "cdaList"})
public class CdaInterfaceController {
- protected String stringUrl = null;
- private StringBuffer result = new StringBuffer();
- private Log log=LogFactory.getLog(CdaInterfaceController.class);
-
- public CdaInterfaceController() {
- // TODO Auto-generated constructor stub
- }
-
- /**
- * all "get" requests to "/sentPatientId.htm" are caught here and the page
- * to display is returned.
- *
- * @param model
- * @return String representing the page too display
- */
-
- @RequestMapping(value = "/sentPatientId.htm", method = RequestMethod.GET)
- public String showUserForm(ModelMap model) {
- PatientIdentification patientId = new PatientIdentification();
- model.addAttribute(patientId);
-
- return "sendPatientInfo";
- }
-
- /**
- * Gets patient Identification and transform this to XML. It pass the XML to
- * URL.
- *
- * @param patientId
- * @return
- */
-
- @RequestMapping(value = "/sentPatientId.htm", method = RequestMethod.POST)
- public String onSubmit(
- @ModelAttribute("patientIdentification") PatientIdentification patientId,
- ModelMap model) {
-
-
- OutputStreamWriter wr = null;
- Properties props = new Properties();
-
- try {
- InputStream in = JavaToXML.getPropertiesFile("config.properties");
- props.load(in);
- in.close();
-
- String stringUrl = props.getProperty("urlMirth");
- System.out.println(patientId.toString());
- String s = JavaToXML.objectToXml(patientId);
- log.info("Message to send : \n"+s);
- System.out.println("Connecting to URL"+stringUrl);
- URL url = new URL(stringUrl);
- URLConnection conn = url.openConnection();
- conn.setDoOutput(true);
- wr = new OutputStreamWriter(conn.getOutputStream());
- wr.write("query=" + s);
- wr.flush();
- wr.close();
- BufferedReader response = new BufferedReader(new InputStreamReader(
- conn.getInputStream()));
- String respString;
- result.setLength(0);
- while ((respString = response.readLine()) != null){
- result.append(respString);
- }
- if (result.length() == 0) {
- String[] errors = new String[1];
- errors[0] = "No Match Found";
- model.addAttribute("errors", errors);
- return "sendPatientInfo";
- }
- return "redirect:receiveCda.htm";
- } catch (Exception e) {
- e.printStackTrace();
- }
- return "sendPatientInfo";
- }
-
- @RequestMapping("/sendSuccess.htm")
- public String sendSuccess() {
-
- return "sendSuccess";
-
- }
-
- /**
- * Need to be refined after the channel is created
- *
- * @param model
- * @param params
- * @return
- */
-
- @RequestMapping(value = "/receiveCda.htm", method = RequestMethod.GET)
- public String receiveCda(ModelMap model) {
- this.addStyleSheet();
- String[] params = new String[1];
- params[0] = this.result.toString();
- model.addAttribute("params", params);
- return "viewCda";
- }
-
- /**
- * Add the XSLT style sheet element to the CDA, which may be avaliable in this.result
- *
- */
- protected void addStyleSheet() {
- // This points to the CDA XSL style sheet served from the root resources dir
- String stylelink = "<?xml-stylesheet type='text/xsl' href='xsl/WebViewLayout_CDA.xsl'?>";
- if (this.result.length() < 1) {
- // No CDA delivered, we're done.
- return;
- }
- // Insert the style sheet element immediately following the xml header
- int endOfHeader = this.result.indexOf(">");
- int i = this.result.indexOf("<?xml-stylesheet", endOfHeader);
- if (i < 0) {
- // No style sheet element, insert ours
- this.result.insert(endOfHeader, stylelink);
- } else {
- // Style sheet present - replace w/ our to be safe
- int endOfStyle = this.result.indexOf(">", i);
- this.result.replace(i, endOfStyle+1, stylelink);
- }
+ protected String stringUrl = null;
+ //private StringBuffer result = new StringBuffer();
+ private Log log = LogFactory.getLog(CdaInterfaceController.class);
+
+ /**
+ * Handles all "GET" requests to "/sentPatientId" are caught here and the
+ * page to display is returned. The resulting form collects search criteria.
+ *
+ * @param model
+ * @return String naming the .jsp page to display
+ */
+ @RequestMapping(value = "/sentPatientId", method = RequestMethod.GET)
+ public String showUserForm(ModelMap model) {
+ PatientIdentification patientId = new PatientIdentification();
+ model.addAttribute(patientId);
+
+ return "sendPatientInfo";
+ }
+
+ /**
+ * Handles all "POST" requests to "/sentPatientId". Uses the patient
+ * criteria from the form to hit the external CDA query service, redirecting
+ * appropriately depending on found results.
+ *
+ * @param patientId
+ * @return String naming the .jsp page to display
+ */
+ @RequestMapping(value = "/sentPatientId", method = RequestMethod.POST)
+ public String onSubmit(
+ @ModelAttribute("patientIdentification") PatientIdentification patientId,
+ ModelMap model) {
+ try {
+ Map<String, String> resultList = executeQuery(patientId);
+ if (resultList.size() == 0) {
+ String[] errors = new String[1];
+ errors[0] = "No Match Found";
+ model.addAttribute("errors", errors);
+ return "sendPatientInfo";
+ } else {
+ // Store matching CDA docs in session
+ model.addAttribute("cdaList", resultList);
+ }
+ return "redirect:sendSuccess";
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return "sendPatientInfo";
+ }
+
+ /**
+ * Redirection target after receiving query results. Displaying the
+ * appropriate meta-data for each matching CDA, with links to view.
+ *
+ * @param cdaList session attribute, containing the search results
+ * @param model
+ * @return String naming the .jsp page to display
+ */
+ @RequestMapping(value = "/sendSuccess", method = RequestMethod.GET)
+ public String sendSuccess(
+ @ModelAttribute("cdaList") Map<String, String> cdaList,
+ ModelMap model) {
+ if (cdaList == null || cdaList.size() < 1) {
+ // Shouldn't be here without a result list - possible in event
+ // of session timeout or bookmarked URL.
+ String[] errors = new String[1];
+ errors[0] = "No Match Found";
+ model.addAttribute("errors", errors);
+ }
+ return "sendSuccess";
+ }
+
+ /**
+ * ReSTful view controller to display a single CDA. Looks first to the
+ * session for the requested cdaID, making a round trip to the external
+ * query service only when necessary.
+ *
+ * @param cdaList session attribute, containing the search results
+ * @param model
+ * @return String naming the .jsp page to display
+ */
+ @RequestMapping(value = "/viewCda/{cdaID}", method = RequestMethod.GET)
+ public String viewCda(
+ @PathVariable String cdaID,
+ @ModelAttribute("cdaList") Map<String, String> cdaList,
+ ModelMap model) {
+ // Check the session for the requested cda
+ String cda = null;
+ if (cdaList != null && cdaList.containsKey(cdaID)) {
+ cda = cdaList.get(cdaID);
+ } else {
+ // Need to round trip to query for requested cda
+ PatientIdentification pid = new PatientIdentification();
+ pid.setCdaID(cdaID);
+ Map<String, String> resultList = executeQuery(pid);
+ //model.addAttribute("cdaList", resultList);
+ cda = resultList.get(cdaID);
+ if (cda == null) {
+ // No match found, redirect to search w/ error
+ String[] errors = new String[1];
+ errors[0] = "No Match Found";
+ model.addAttribute("errors", errors);
+ return "viewCda";
+ }
+ }
+ cda = this.addStyleSheet(new StringBuffer(cda));
+ String[] params = new String[1];
+ params[0] = cda;
+ model.addAttribute("params", params);
+ return "viewCda";
+ }
+
+ /**
+ * Create the "cdaList" session bound attribute if necessary. Called by the
+ * spring framework if no such named attribute can be found in the Model.
+ *
+ * @return the empty (but valid) Map<String, String>
+ */
+ @ModelAttribute("cdaList")
+ public Map<String, String> createCdaList() {
+ return new HashMap<String, String>();
+ }
+
+ /**
+ * Create the "patientIdentification" session bound attribute if necessary.
+ * Called by the spring framework if no such named attribute can be found in
+ * the Model.
+ *
+ * @return a new PatientIdentification
+ */
+ @ModelAttribute("patientIdentification")
+ public PatientIdentification createPatientId() {
+ return new PatientIdentification();
+ }
+
+ /**
+ * Add the XSLT style sheet element to the CDA
+ *
+ * @param cda The CDA, XML document to inject with the configured .xsl
+ * @return String representation of the CDA, including the stylesheet.
+ */
+ protected String addStyleSheet(StringBuffer cda) {
+ // This points to the CDA XSL style sheet served from the root resources dir
+ String stylelink = "<?xml-stylesheet type='text/xsl' href='xsl/WebViewLayout_CDA.xsl'?>";
+ if (cda.length() < 1 || cda.indexOf(">") < 0) {
+ // CDA doesn't look like XML, raise
+ throw new RuntimeException("Invalid document");
+ }
+ // Insert the style sheet element immediately following the xml header
+ int endOfHeader = cda.indexOf(">");
+ int i = cda.indexOf("<?xml-stylesheet", endOfHeader);
+ if (i < 0) {
+ // No style sheet element, insert ours
+ cda.insert(endOfHeader + 1, stylelink);
+ } else {
+ // Style sheet present - replace w/ our to be safe
+ int endOfStyle = cda.indexOf(">", i);
+ cda.replace(i, endOfStyle + 1, stylelink);
+ }
+ return cda.toString();
+ }
+
+ /**
+ * Execute a query for one or more CDA documents and meta data.
+ *
+ * Make an HTTP request to external service, i.e. the CDA query mirth
+ * channel.
+ *
+ * @param patientId with attributes set to query.
+ * @return map of <cdaId: cda xml document> for any matching CDAs found.
+ */
+ private Map<String, String> executeQuery(PatientIdentification patientId) {
+ Map<String, String> results = null;
+ try {
+ OutputStreamWriter wr = null;
+ Properties props = new Properties();
+
+ InputStream in = JavaToXML.getPropertiesFile("config.properties");
+ props.load(in);
+ in.close();
+
+ String stringUrl = props.getProperty("urlMirth");
+ String s = JavaToXML.objectToXml(patientId);
+ log.info("Message to send : \n" + s);
+ URL url = new URL(stringUrl);
+ URLConnection conn = url.openConnection();
+ conn.setDoOutput(true);
+ wr = new OutputStreamWriter(conn.getOutputStream());
+ wr.write("query=" + s);
+ wr.flush();
+ wr.close();
+
+ CdaQueryResult cdaQueryResult = new CdaQueryResult();
+ results = cdaQueryResult.parseDocument(conn.getInputStream());
+ } catch (IOException ex) {
+ Logger.getLogger(CdaInterfaceController.class.getName()).log(Level.SEVERE, null, ex);
}
+ return results;
+ }
}
View
108 oec2Interface/src/main/java/ke/go/moh/oec/pisinterfaces/util/CdaQueryResult.java
@@ -0,0 +1,108 @@
+package ke.go.moh.oec.pisinterfaces.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+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>();
+
+ /**
+ * SAX parser implementation used to parse a document returned from the
+ * external CDA query service.
+ *
+ * @param document the result document from a query request
+ * @return a map of {cda_id: cda} for each cda found in the doc.
+ */
+ public Map<String, String> parseDocument(InputStream document) {
+
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ try {
+ SAXParser saxParser = spf.newSAXParser();
+
+ DefaultHandler handler = new DefaultHandler() {
+
+ boolean cda_id_element = false;
+ boolean cda_element = false;
+ String cda_id = null;
+ StringBuffer cda_buffer = new StringBuffer();
+
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ if (qName.equalsIgnoreCase("cda_id")) {
+ cda_id_element = true;
+ }
+ if (qName.equalsIgnoreCase("cda")) {
+ cda_element = true;
+ }
+ }
+
+ 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, to avoid any
+ // nested CDATA decoding trouble.
+ byte[] decodedBytes = Base64.decodeBase64(cda_buffer.toString());
+ String cda = new String(decodedBytes);
+
+ CdaQueryResult.this.cdaList.put(cda_id, cda);
+ cda_id = null;
+ cda_buffer.setLength(0);
+ }
+ if (qName.equalsIgnoreCase("cda_id")) {
+ assert (cda_id_element == true);
+ cda_id_element = false;
+ }
+ if (qName.equalsIgnoreCase("cda")) {
+ assert (cda_element == true);
+ cda_element = false;
+ }
+ }
+
+ public void characters(char ch[], int start, int length) throws SAXException {
+
+ if (cda_id_element) {
+ assert (cda_id == null);
+ cda_id = new String(ch, start, length);
+ }
+ if (cda_element) {
+ cda_buffer.append(ch, start, length);
+ }
+ }
+ };
+
+ saxParser.parse(document, handler);
+
+ } catch (SAXException se) {
+ se.printStackTrace();
+ } catch (ParserConfigurationException pce) {
+ pce.printStackTrace();
+ } catch (IOException ie) {
+ ie.printStackTrace();
+ }
+ return cdaList;
+ }
+}
View
11 oec2Interface/src/main/webapp/WEB-INF/jsp/sendSuccess.jsp
@@ -1,12 +1,19 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
+<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
-<title>Insert title here</title>
+<title>CDA Query Result</title>
</head>
<body>
-
+ <c:if test="${not empty errors}">${errors[0]}</c:if>
+ <p><a href="sentPatientId">New search</a></p>
+ <ul>
+ <c:forEach var="cda" items="${cdaList}">
+ <li><a href="viewCda/${cda.key}">${cda.key}</a></li>
+ </c:forEach>
+ </ul>
</body>
</html>
View
4 oec2Interface/src/main/webapp/WEB-INF/jsp/viewCda.jsp
@@ -1 +1,3 @@
-${params[0]}
+<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<c:if test="${not empty errors}">${errors[0]}</c:if>
+<c:if test="${not empty params}">${params[0]}</c:if>
View
2 oec2Interface/src/main/webapp/WEB-INF/web.xml
@@ -16,6 +16,6 @@
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
- <url-pattern>*.htm</url-pattern>
+ <url-pattern>/cda/*</url-pattern>
</servlet-mapping>
</web-app>
View
2 oec2Interface/src/main/webapp/index.jsp
@@ -1,2 +1,2 @@
<%@page contentType="text/html" pageEncoding="UTF-8"%>
-<% response.sendRedirect("sentPatientId.htm"); %>
+<% response.sendRedirect("/cda/sentPatientId"); %>
View
57 oec2Interface/src/test/java/ke/go/moh/oec/pisinterfaces/util/CdaQueryResultTest.java
@@ -0,0 +1,57 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package ke.go.moh.oec.pisinterfaces.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author pbugni
+ */
+public class CdaQueryResultTest extends TestCase {
+
+ public CdaQueryResultTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of parseDocument method, of class CdaQueryResult.
+ */
+ public void testParseDocument() {
+ InputStream testFile = null;
+ try {
+ CdaQueryResult instance = new CdaQueryResult();
+ testFile = getClass().getResourceAsStream("/cda_query_result.xml");
+ Map <String, String> results = instance.parseDocument(testFile);
+ assert(results.size() == 2);
+ // Key should be an integer (pk) and Value in each should be a valid CDA
+ for (Map.Entry<String, String> entry : results.entrySet()){
+ int pk = Integer.parseInt(entry.getKey());
+ assert(pk >= 0);
+ String cda_doc = entry.getValue();
+ assertTrue(cda_doc.startsWith("<?xml version="));
+ }
+ } finally {
+ try {
+ testFile.close();
+ } catch (IOException ex) {
+ fail(ex.getLocalizedMessage());
+ }
+ }
+ }
+}
View
1 oec2Interface/src/test/resources/cda_query_result.xml
1 addition, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.

0 comments on commit 1eb38a0

Please sign in to comment.
Something went wrong with that request. Please try again.