/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package gov.hhs.fha.nhinc.cpp; import com.sun.imageio.plugins.common.InputStreamAdapter; import gov.hhs.fha.nhinc.mpilib.*; import org.w3c.dom.*; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.stream.*; import sun.util.logging.resources.logging; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.stream.*; import java.io.StringWriter; import gov.hhs.fha.nhinc.mpilib.PersonName; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.StringReader; import org.xml.sax.InputSource; import org.xml.sax.helpers.XMLReaderAdapter; import gov.hhs.fha.nhinc.properties.PropertyAccessor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * * @author dunnek */ public class CPPUtils { private static Log log = LogFactory.getLog(CPPUtils.class); static final String OPT_IN_RULE_ID = "126"; static final String OPT_OUT_RULE_ID = "125"; static final String DENY_DESCR = "deny all access to documents."; static final String PERMIT_DESCR = "permit all access to documents."; static final String OPT_IN_EFFECT = "Permit"; static final String OPT_OUT_EFFECT = "Deny"; private static final String RULE_TAG = "Rule"; private static final String RULE_ID_ATTR = "RuleId"; private static final String RULE_EFFECT_ATTR = "Effect"; private static final String ROOT_ATTR = "Root"; private static final String PATID_TAG = "PatientId"; private static final int SEND_SLEEP_COUNT = 15; private static final long SEND_SLEEP_TIME_MS = 1000L; private static final String basePolicy = "" + " " + "Sample XACML policy showing access by user role " + " " + " " + " " + " " + " " + " http://www.hhs.gov/healthit/nhin#retrieveDocument " + " " + " " + " " + " " + " " + "" + " " + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "" + " "; public static boolean defaultOptIn() { boolean optIn; try { optIn = PropertyAccessor.getPropertyBoolean("gateway", "RetrieveDocdefaultOptIn"); } catch (Exception ex) { optIn = false; } return optIn; } public static String DocumentToString(Document doc) { String xmlString; //initialize StreamResult with File object to save to file StreamResult result = new StreamResult(new StringWriter()); DOMSource source = new DOMSource(doc); try { Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.transform(source, result); xmlString = result.getWriter().toString(); } catch (Exception ex) { xmlString = ""; } return xmlString; } public static Document ByteArrayToDoc(byte[] rawData) { Document doc = null; try { DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = builderFactory.newDocumentBuilder(); doc = builder.newDocument(); InputStream stream = new ByteArrayInputStream(rawData); doc = builder.parse(new InputSource(stream)); } catch (Exception ex) { } return doc; } public static Identifier extractPatientId(Document doc) { Identifier id; String orgId; String patId; orgId = doc.getElementsByTagName("PatientId").item(0).getAttributes().getNamedItem("Root").getNodeValue(); patId = doc.getElementsByTagName("PatientId").item(0).getAttributes().getNamedItem("Extension").getNodeValue(); id = new Identifier(patId, orgId); return id; } public static boolean isOptedIn(Document doc) { Node rule = doc.getElementsByTagName(RULE_TAG).item(0); String ruleId = ""; if (rule != null) { ruleId = rule.getAttributes().getNamedItem(RULE_ID_ATTR).getNodeValue(); } else { //If no cpp document exists for the patient, go with the site's //default opt in value. if (defaultOptIn()) { ruleId = OPT_IN_RULE_ID; } } return (ruleId.equals(OPT_IN_RULE_ID)); } public static boolean isOptedIn(String patId, String orgId) { CPPOperations ops = new CPPOperations(); gov.hhs.fha.nhinc.repository.model.Document cppDoc; boolean optedIn = false; cppDoc = ops.retreiveCPP(patId, orgId); if (cppDoc != null) { if (cppDoc.getRawData() != null) { optedIn = isOptedIn(ByteArrayToDoc(cppDoc.getRawData())); } else { optedIn = defaultOptIn(); } } else { //If no cpp document exists for the patient, go with the site's //default opt in value. optedIn = defaultOptIn(); } return optedIn; } public static void Save(Patients pats) { for (Patient pat : pats) { Save(pat); } } public static void Save(Patient pat) { Document doc = createXAML(pat); String xacml = DocumentToString(doc); CPPOperations ops = new CPPOperations(); ops.init(pat.getIdentifiers().get(0).getId(), pat.getIdentifiers().get(0).getOrganizationId(), xacml); ops.start(); // Check for the results of sending the subscribe message from the thread boolean resultsReceived = false; boolean sendSuccess = false; int waitCount = 0; while (!resultsReceived && (waitCount < SEND_SLEEP_COUNT)) { if (ops.isFinished()) { resultsReceived = true; sendSuccess = ops.isSendSuccessful(); if (log.isDebugEnabled()) { log.debug("Subscribe send results received: " + sendSuccess); } } else { if (log.isDebugEnabled()) { log.debug("Subscribe send not completed - waiting for results - loop index: " + waitCount); } try { Thread.sleep(SEND_SLEEP_TIME_MS); } catch (Throwable t) { // Eat error and continue } } waitCount++; } } public static Document[] createXAML(Patients pats) { Document[] docs = new Document[pats.size()]; for (int x = 0; x < pats.size(); x++) { docs[x] = createXAML(pats.get(x)); } return docs; } public static Document createXAML(Patient p) { Document doc = null; try { DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = builderFactory.newDocumentBuilder(); //doc = builder.parse (new org.xml.sax.InputSource ("\\src\\java\\gov\\hhs\\fha\\nhinc\\xaml\\basePolicy.xml")); doc = builder.newDocument(); StringReader reader = new StringReader(basePolicy); doc = builder.parse(new InputSource(reader)); builder.parse(new InputSource(new StringReader(basePolicy))); doc = populatePatientInfo(doc, p); Element rule = populateOptInOut(doc, p); doc.getFirstChild().appendChild(rule); doc.setXmlStandalone(true); doc.normalizeDocument(); } catch (Exception ex) { String error = ex.getMessage(); } return doc; } private static Document populatePatientInfo(Document doc, Patient p) { Node pat = doc.getElementsByTagName("PatientId").item(0); Identifier id = p.getIdentifiers().get(0); pat.getAttributes().getNamedItem("Root").setNodeValue(id.getOrganizationId()); pat.getAttributes().getNamedItem("Extension").setNodeValue(id.getId()); return doc; } private static Element populateOptInOut(Document doc, Patient p) { if (p.isOptedIn()) { return populateOptIn(doc); } else { return populateOptOut(doc); } } private static Element populateOptOut(Document doc) { Element optOut = doc.createElement(RULE_TAG); optOut.setAttribute(RULE_ID_ATTR, OPT_OUT_RULE_ID); optOut.setAttribute(RULE_EFFECT_ATTR, OPT_OUT_EFFECT); Element descr = doc.createElement("Description"); descr.setTextContent(DENY_DESCR); optOut.appendChild(descr); optOut.appendChild(doc.createElement("Target")); return optOut; } private static Element populateOptIn(Document doc) { Element optIN = doc.createElement(RULE_TAG); optIN.setAttribute(RULE_ID_ATTR, OPT_IN_RULE_ID); optIN.setAttribute(RULE_EFFECT_ATTR, OPT_IN_EFFECT); Element descr = doc.createElement("Description"); descr.setTextContent(PERMIT_DESCR); optIN.appendChild(descr); optIN.appendChild(doc.createElement("Target")); return optIN; } }