<%@ page language="java"%> <% String downloadDirectory = "c:/temp/"; %> <%@page import="java.io.PrintWriter"%> <%@page import="java.io.FileWriter"%> <%@page import="java.io.File"%> <%@page import="java.util.Date"%> <%@page import="java.text.SimpleDateFormat"%> <%@page import="java.util.ArrayList"%> <%@page import="java.util.Iterator"%> Meaningful Use

*** State Registry Name ***

Meaningful Use Attestation

<% /* These are the variables that are collected for attestation. You can add your own here as needed. */ String orgName = ""; String contactName = ""; String contactPhone = ""; String contactEmail = ""; String softwareName = ""; String softwareVersion = ""; String messageData = ""; String action = request.getParameter("action"); if (action == null) { action = ""; } ArrayList rxaSegmentFields = new ArrayList(); if (action.equals("Submit")) { /* This code is only run if the report is being submitted. */ orgName = request.getParameter("orgName").trim(); contactName = request.getParameter("contactName").trim(); contactPhone = request.getParameter("contactPhone").trim(); contactEmail = request.getParameter("contactEmail").trim(); softwareName = request.getParameter("softwareName").trim(); softwareVersion = request.getParameter("softwareVersion").trim(); messageData = request.getParameter("messageData").trim(); ArrayList problems = new ArrayList(); /* The following code checks the fields for minimum lengths and also ensures that extremely dodgy data is not sent, such as unprintable characters. */ /* Organization Name */ String fieldName = "Organization Name"; String field = orgName; if (field == null || field.length() < 3) { problems.add(fieldName + " must be at least 3 characters"); } else { char c; for (int i = 0; i < field.length(); i++) { c = field.charAt(i); if (c < ' ' || c > 128) { problems.add(fieldName + " has an illegal or unexpected character"); } } } if (field.length() > 100) { field = field.substring(0, 100); } orgName = field; /* Contact Name */ fieldName = "Contact Name"; field = contactName; if (field == null || field.length() < 3) { problems.add(fieldName + " must be at least 3 characters"); } else { char c; for (int i = 0; i < field.length(); i++) { c = field.charAt(i); if (c < ' ' || c > 128) { problems.add(fieldName + " has an illegal or unexpected character"); } } } if (field.length() > 100) { field = field.substring(0, 100); } contactName = field; /* Contact Phone */ fieldName = "Contact Phone"; field = contactPhone; if (field == null || field.length() < 3) { problems.add(fieldName + " must be at least 3 characters"); } else { char c; for (int i = 0; i < field.length(); i++) { c = field.charAt(i); if (c < ' ' || c > 128) { problems.add(fieldName + " has an illegal or unexpected character"); } } } if (field.length() > 100) { field = field.substring(0, 100); } /* Contact Phone */ contactPhone = field; fieldName = "Contact Email"; field = contactEmail; if (field == null || field.length() < 3) { problems.add(fieldName + " must be at least 3 characters"); } else { char c; for (int i = 0; i < field.length(); i++) { c = field.charAt(i); if (c < ' ' || c > 128) { problems.add(fieldName + " has an illegal or unexpected character"); } } } if (field.length() > 100) { field = field.substring(0, 100); } contactEmail = field; /* Software Name */ fieldName = "Software Name"; field = softwareName; if (field == null || field.length() < 3) { problems.add(fieldName + " must be at least 3 characters"); } else { char c; for (int i = 0; i < field.length(); i++) { c = field.charAt(i); if (c < ' ' || c > 128) { problems.add(fieldName + " has an illegal or unexpected character"); } } } if (field.length() > 100) { field = field.substring(0, 100); } softwareName = field; /* Software Version */ fieldName = "Software Version"; field = orgName; if (field == null || field.length() < 3) { } else { char c; for (int i = 0; i < field.length(); i++) { c = field.charAt(i); if (c < ' ' || c > 128) { problems.add(fieldName + " has an illegal or unexpected character"); } } } if (field.length() > 100) { field = field.substring(0, 100); } softwareVersion = field; /* Now it's time to do some very basic checks, just to make sure we have something that looks remotely like HL7. */ int startPos = 0; while (messageData.length() > startPos && messageData.charAt(startPos) <= ' ') { startPos++; } if (startPos > 0 && startPos < messageData.length()) { messageData = messageData.substring(startPos); } /* Checking to see if the first segment is an HL7 header segment. */ if (messageData.length() < 10 || (!messageData.startsWith("MSH") && !messageData.startsWith("BHS") && !messageData.startsWith("FHS"))) { problems.add("Message does not appear to be HL7, should start with MSH, BHS or FHS segments"); } /* If the message is really long we want to reject. This keeps us from having performance problems. This was not built to attest for large files. Normally providers are only sending one or two messages. */ if (messageData.length() > 1024 * 900) { problems.add("Message batches larger than 900 KB are not accepted"); } if (problems.size() == 0) { /* Now it is time to look through the segments and look for vaccinations. The parsing algorithm breaks a segment on non-printable characters. This allows for alternative line breaking and for the standard HL7 line breaking. Blank or short lines are skipped. */ ArrayList segments = new ArrayList(); boolean newSegment = true; String line = ""; for (int i = 0; i < messageData.length(); i++) { char c = messageData.charAt(i); if (c < ' ') { if (line.length() > 4) { segments.add(line); } line = ""; } else { line = line + c; } } if (line.length() > 4) { segments.add(line); } /* Now it's time to pull out the RXA segments. */ for (int i = 0; i < segments.size(); i++) { String segment = (String) segments.get(i); String[] fields = segment.split("\\|"); if (fields[0].equals("RXA")) { rxaSegmentFields.add(fields); } else if (fields[0].equals("MSH")) { if (fields.length < 8 || !fields[8].startsWith("VXU")) { problems.add("Unexpected message type: '" + (fields.length < 8 ? "" : fields[8]) + "', expecting VXU"); } } } /* For a success we really have to see at least one RXA. */ if (rxaSegmentFields.size() == 0) { problems.add("No RXA segments in file"); } /* At the very least one of them should have a date and vaccine code. */ boolean foundOneGoodOne = false; for (Iterator it = rxaSegmentFields.iterator(); it.hasNext();) { String[] fields = (String[]) it.next(); if (fields.length > 5 && !fields[3].equals("") && !fields[5].equals("")) { foundOneGoodOne = true; } } if (!foundOneGoodOne) { problems.add("No RXA segments found with values in RXA-3 and RXA-5"); } } /* If we found more than one problem then we display the error message. */ if (problems.size() > 0) { %>

Unable to accept meaningful use message.

Submitted Data:

<%= messageData %> <% } else { /* If the data is good it needs to be saved to the file. */ File baseDir = new File(downloadDirectory); if (!baseDir.exists()) { /* Make the directory if it's not there yet. */ baseDir.mkdirs(); } SimpleDateFormat sdf = new SimpleDateFormat(); /* File name is based on the organization name indicated by user. */ /* The safe name has all non numeric and alphabetic characters removed. This is to ensure there are no problems making the file name from a user entered value. */ String safeOrgName = ""; for (int i = 0; i < orgName.length(); i++) { char c = orgName.charAt(i); if (c == ' ' || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { safeOrgName += c; } } String filename = "MU " + safeOrgName.trim() + ".txt"; File file = new File(baseDir, filename); if (file.exists() && file.length() > 10 * 1024 * 1024) { /* File is now bigger than 10 MB. We should not accept any more submissions from this provider. This is to protect from someone sending a large amount of data too many times and loading up the drive with too much data. */ %>

The maximum amount of meaningful use data allowed to be sent has been received. Thank you for your submissions, please *** contact registry help desk for assistance. ***

<% } else { /* File is opened for append. If this is run again by same clinic it is just tacked onto the original file. */ PrintWriter pw = new PrintWriter(new FileWriter(file, true)); pw.println("-----------------------------------------------------------"); pw.println("Submission Date: " + sdf.format(new Date())); pw.println("Organization Name: " + orgName); pw.println("Contact Name: " + contactName); pw.println("Contact Phone: " + contactPhone); pw.println("Contact Email: " + contactEmail); pw.println("Software Name: " + softwareName); pw.println("Software Version: " + softwareVersion); pw.println(); pw.println(messageData); pw.println(); pw.close(); %>

Submission Successful

*** Put appropriate language to make this page an official attestation report. This should include language that indicates that the sender has complied with the intent of meaningful use to submit an HL7 message to to the immunization registry. Instructions should be given to indicate what next steps could be done to receive feedback from the registry about how to make additional submissions. ***

Submission Date<%= sdf.format(new Date()) %>
Organization Name<%= orgName %>
Contact Name<%= contactName %>
Contact Phone<%= contactPhone %>
Contact Email<%= contactEmail %>
Software Name<%= softwareName %>
Software Version<%= softwareVersion %>

<%= rxaSegmentFields.size() %> Vaccination<%= rxaSegmentFields.size() == 1 ? "" : "s" %> Found

<% for (Iterator it = rxaSegmentFields.iterator(); it.hasNext(); ) { String[] fields = (String[]) it.next(); if (fields.length > 5) { %> <% } } %>
Date Administered Administration Code(s)
<%= fields[3] %> <%= fields[5] %>
<% } } } else { %>
Organization Name
Contact Name
Contact Phone
Contact Email
Software Name
Software Version
HL7 Messages
<% } %>