/*******************************************************************************
* Open Behavioral Health Information Technology Architecture (OBHITA.org)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
package gov.samhsa.consent2share.showcase.service;
import gov.samhsa.acs.common.tool.SimpleMarshaller;
import gov.samhsa.acs.xdsb.common.XdsbDocumentType;
import gov.samhsa.consent2share.hl7.Hl7v3TransformerException;
import gov.samhsa.consent2share.pixclient.service.PixManagerService;
import gov.samhsa.consent2share.pixclient.util.PixManagerBean;
import gov.samhsa.consent2share.pixclient.util.PixManagerConstants;
import gov.samhsa.consent2share.pixclient.util.PixManagerRequestXMLToJava;
import gov.samhsa.consent2share.showcase.exception.AcsShowCaseException;
import gov.samhsa.consent2share.showcase.exception.XmlAttributeSetterException;
import gov.samhsa.consent2share.showcase.infrastructure.PixOperation;
import gov.samhsa.consent2share.showcase.infrastructure.XdsbRegistryGetter;
import gov.samhsa.consent2share.showcase.infrastructure.XdsbRepositoryService;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBException;
import oasis.names.tc.ebxml_regrep.xsd.rs._3.RegistryResponse;
import org.apache.commons.jxpath.JXPathContext;
import org.hl7.v3.types.II;
import org.hl7.v3.types.MCCIIN000002UV01;
import org.hl7.v3.types.MCCIMT000200UV01Acknowledgement;
import org.hl7.v3.types.MCCIMT000200UV01AcknowledgementDetail;
import org.hl7.v3.types.MCCIMT000300UV01Acknowledgement;
import org.hl7.v3.types.MCCIMT000300UV01AcknowledgementDetail;
import org.hl7.v3.types.PRPAIN201301UV02;
import org.hl7.v3.types.PRPAIN201302UV02;
import org.hl7.v3.types.PRPAIN201309UV02;
import org.hl7.v3.types.PRPAIN201310UV02;
import org.hl7.v3.types.PRPAMT201307UV02PatientIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* The Class PixOperationsServiceImpl.
*/
@Service
public class PixOperationsServiceImpl implements PixOperationsService {
/** The logger. */
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/** The request xml to java. */
@Autowired
private PixManagerRequestXMLToJava requestXMLToJava;
/** The pix mgr bean. */
private PixManagerBean pixMgrBean = new PixManagerBean();
/** The pix mgr service. */
@Autowired
private PixManagerService pixMgrService;
/** The marshaller. */
@Autowired
private SimpleMarshaller marshaller;
/** The pix manager transform service. */
@Autowired
PixManagerTransformService pixManagerTransformService;
/** The xdsb registry getter. */
@Autowired
XdsbRegistryGetter xdsbRegistryGetter;
/** The xdsb repository. */
@Autowired
private XdsbRepositoryService xdsbRepository;
/** The xml attribute setter. */
@Autowired
private XmlAttributeSetter xmlAttributeSetter;
/** The intermediary subject npi. */
@Value("${intermediarySubjectNPI}")
private String intermediarySubjectNPI;
/** The assigning authority name. */
@Value("${assigningAuthorityName}")
private String assigningAuthorityName;
/** The assigning authority oid. */
@Value("${assigningAuthorityOID}")
private String assigningAuthorityOID;
/*
* (non-Javadoc)
*
* @see gov.samhsa.consent2share.showcase.service.PixOperationsService#
* addPatientRegistryRecord(java.lang.String)
*/
@Override
public MCCIIN000002UV01 addPatientRegistryRecord(String c32xml) {
final PixOperation pixOperation = PixOperation.ADD;
return pidFeed(pixOperation, c32xml);
}
/*
* (non-Javadoc)
*
* @see
* gov.samhsa.consent2share.pixclient.client.PixManagerClientService#addPerson
* (java.lang.String)
*/
@Override
public String addPerson(String reqXMLPath) {
// Convert c32 to pixadd string
PRPAIN201301UV02 request = new PRPAIN201301UV02();
MCCIIN000002UV01 response = new MCCIIN000002UV01();
// Delegate to webServiceTemplate for the actual pixadd
try {
// xmlFilePath = "xml/PRPA_IN201301UV02_PIXADD_VD1_Req.xml";
request = requestXMLToJava.getPIXAddReqObject(reqXMLPath,
PixManagerConstants.ENCODE_STRING);
response = pixMgrService.pixManagerPRPAIN201301UV02(request);
getAddUpdateMessage(response, pixMgrBean,
PixManagerConstants.PIX_ADD);
} catch (final JAXBException e) {
getGeneralExpMessage(e, pixMgrBean, PixManagerConstants.PIX_ADD);
} catch (final IOException e) {
getGeneralExpMessage(e, pixMgrBean, PixManagerConstants.PIX_ADD);
}
return pixMgrBean.getAddMessage();
}
/**
* Gets the marshaller.
*
* @return the marshaller
*/
public SimpleMarshaller getMarshaller() {
return marshaller;
}
/**
* Gets the xdsb repository.
*
* @return the xdsb repository
*/
public XdsbRepositoryService getXdsbRepository() {
return xdsbRepository;
}
/**
* Gets the xml attribute setter.
*
* @return the xml attribute setter
*/
public XmlAttributeSetter getXmlAttributeSetter() {
return xmlAttributeSetter;
}
/*
* (non-Javadoc)
*
* @see gov.samhsa.consent2share.pixclient.client.PixManagerClientService#
* provideAndRegisterClinicalDocument(java.lang.String)
*/
@Override
public RegistryResponse provideAndRegisterClinicalDocument(String c32xml) {
c32xml = updatePatientAndAuthorId(c32xml);
return xdsbRepository.provideAndRegisterDocumentSet(c32xml,
PixManagerConstants.GLOBAL_DOMAIN_ID,
XdsbDocumentType.CLINICAL_DOCUMENT);
}
/*
* (non-Javadoc)
*
* @see
* gov.samhsa.consent2share.pixclient.client.PixManagerClientService#queryPerson
* (java.lang.String)
*/
@Override
public PixManagerBean queryPerson(String xmlFilePath) {
logger.debug("Received request to PIXQuery");
PRPAIN201309UV02 request = new PRPAIN201309UV02();
PRPAIN201310UV02 response = new PRPAIN201310UV02();
// Delegate to webServiceTemplate for the actual pixadd
try {
request = requestXMLToJava.getPIXQueryReqObject(xmlFilePath,
PixManagerConstants.ENCODE_STRING);
response = pixMgrService.pixManagerPRPAIN201309UV02(request);
pixMgrBean = new PixManagerBean();
getQueryMessage(response, pixMgrBean);
} catch (final JAXBException e) {
getGeneralExpMessage(e, pixMgrBean, PixManagerConstants.PIX_QUERY);
} catch (final IOException e) {
getGeneralExpMessage(e, pixMgrBean, PixManagerConstants.PIX_QUERY);
}
return pixMgrBean;
}
/*
* (non-Javadoc)
*
* @see gov.samhsa.consent2share.showcase.service.PixOperationsService#
* revisePatientRegistryRecord(java.lang.String)
*/
@Override
public MCCIIN000002UV01 revisePatientRegistryRecord(String c32xml) {
final PixOperation pixOperation = PixOperation.UPDATE;
return pidFeed(pixOperation, c32xml);
}
/**
* Sets the marshaller.
*
* @param marshaller
* the new marshaller
*/
public void setMarshaller(SimpleMarshaller marshaller) {
this.marshaller = marshaller;
}
/**
* Sets the pix manager transform service.
*
* @param pixManagerTransformService
* the new pix manager transform service
*/
public void setPixManagerTransformService(
PixManagerTransformService pixManagerTransformService) {
this.pixManagerTransformService = pixManagerTransformService;
}
/**
* Sets the pix mgr service.
*
* @param pixMgrService
* the new pix mgr service
*/
public void setPixMgrService(PixManagerService pixMgrService) {
this.pixMgrService = pixMgrService;
}
/**
* Sets the request xml to java.
*
* @param requestXMLToJava
* the new request xml to java
*/
public void setRequestXMLToJava(PixManagerRequestXMLToJava requestXMLToJava) {
this.requestXMLToJava = requestXMLToJava;
}
/**
* Sets the xdsb registry getter.
*
* @param xdsbRegistryGetter
* the new xdsb registry getter
*/
public void setXdsbRegistryGetter(XdsbRegistryGetter xdsbRegistryGetter) {
this.xdsbRegistryGetter = xdsbRegistryGetter;
}
/**
* Sets the xdsb repository.
*
* @param xdsbRepository
* the new xdsb repository
*/
public void setXdsbRepository(XdsbRepositoryService xdsbRepository) {
this.xdsbRepository = xdsbRepository;
}
/**
* Sets the xml attribute setter.
*
* @param xmlAttributeSetter
* the new xml attribute setter
*/
public void setXmlAttributeSetter(XmlAttributeSetter xmlAttributeSetter) {
this.xmlAttributeSetter = xmlAttributeSetter;
}
@Override
public String updatePatientAndAuthorId(String c32xml) {
String hl7v3Xml = null;
try {
hl7v3Xml = pixManagerTransformService.getPixQueryXml(c32xml);
} catch (final Hl7v3TransformerException e) {
logger.error(e.getMessage(), e);
throw new AcsShowCaseException(
"PixOperationsService is failed! Cannot get PIX Query XML from PIX Manager Transform Service!");
}
final PixManagerBean pixManagerBean = queryPerson(hl7v3Xml);
final Map<String, String> queryMap = pixManagerBean.getQueryIdMap();
String eid = null;
if (null != queryMap) {
// get Eid Values
eid = queryMap.get(PixManagerConstants.GLOBAL_DOMAIN_ID);
final String xPathExpr = "//hl7:recordTarget/child::hl7:patientRole/child::hl7:id";
try {
c32xml = xmlAttributeSetter.setAttributeValue(c32xml,
xPathExpr, "extension", eid);
c32xml = xmlAttributeSetter
.setAttributeValue(c32xml, xPathExpr, "root",
PixManagerConstants.GLOBAL_DOMAIN_ID);
c32xml = xmlAttributeSetter.setAttributeValue(c32xml,
xPathExpr, "assigningAuthorityName",
PixManagerConstants.GLOBAL_DOMAIN_NAME);
// TODO: These 4 lines below is added to manually insert author
// id (intermediarySubjectNPI), because it is not populated by
// REM.
final String authorIdXpath = "//hl7:author/child::hl7:assignedAuthor/child::hl7:id";
c32xml = xmlAttributeSetter
.setAttributeValue(c32xml, authorIdXpath, "extension",
this.intermediarySubjectNPI);
c32xml = xmlAttributeSetter.setAttributeValue(c32xml,
authorIdXpath, "root", this.assigningAuthorityOID);
c32xml = xmlAttributeSetter.setAttributeValue(c32xml,
authorIdXpath, "assigningAuthorityName",
this.assigningAuthorityName);
} catch (final XmlAttributeSetterException e) {
logger.error(e.getMessage(), e);
throw new AcsShowCaseException(
"PixOperationsService failed! Cannot run the XPath Expression!");
} catch (final Exception e) {
logger.error(e.getMessage(), e);
throw new AcsShowCaseException(
"PixOperationsService failed! Unexpected problem occured!");
}
} else {
logger.error("Error! queryMap is null, eid cannot be retrieved!");
throw new AcsShowCaseException(
"PixOperationsService failed! Cannot retrieve EID.");
}
return c32xml;
}
/*
* (non-Javadoc)
*
* @see gov.samhsa.consent2share.pixclient.client.PixManagerClientService#
* updatePerson(java.lang.String)
*/
@Override
public String updatePerson(String reqXMLPath) {
logger.debug("Received request to PIXUpdate");
PRPAIN201302UV02 request = new PRPAIN201302UV02();
MCCIIN000002UV01 response = new MCCIIN000002UV01();
// Delegate to webServiceTemplate for the actual pixadd
try {
request = requestXMLToJava.getPIXUpdateReqObject(reqXMLPath,
PixManagerConstants.ENCODE_STRING);
response = pixMgrService.pixManagerPRPAIN201302UV02(request);
getAddUpdateMessage(response, pixMgrBean,
PixManagerConstants.PIX_UPDATE);
} catch (final JAXBException e) {
getGeneralExpMessage(e, pixMgrBean, PixManagerConstants.PIX_UPDATE);
} catch (final IOException e) {
getGeneralExpMessage(e, pixMgrBean, PixManagerConstants.PIX_UPDATE);
}
return pixMgrBean.getUpdateMessage();
}
/**
* Gets the adds the update message.
*
* @param response
* the response
* @param pixMgrBean
* the pix mgr bean
* @param msg
* the msg
* @return the adds the update message
*/
protected void getAddUpdateMessage(MCCIIN000002UV01 response,
PixManagerBean pixMgrBean, String msg) {
// The message has been sent
// But it doesn't mean we're subscribed successfully
logger.debug("response ack code:" + response.getAcceptAckCode());
logger.debug("response type id: " + response.getTypeId());
final List<MCCIMT000200UV01Acknowledgement> ackmntList = response
.getAcknowledgement();
for (final MCCIMT000200UV01Acknowledgement ackmnt : ackmntList) {
if (ackmnt.getTypeCode().getCode().equals("CA")) {
if (PixManagerConstants.PIX_ADD.equalsIgnoreCase(msg)) {
pixMgrBean.setAddMessage(msg + " Success! ");
} else if (PixManagerConstants.PIX_UPDATE.equalsIgnoreCase(msg)) {
pixMgrBean.setUpdateMessage(msg + " Success! ");
}
break;
} else if (ackmnt.getTypeCode().getCode().equals("CE")) {
final List<MCCIMT000200UV01AcknowledgementDetail> ackmntDetList = ackmnt
.getAcknowledgementDetail();
for (final MCCIMT000200UV01AcknowledgementDetail ackDet : ackmntDetList) {
logger.error(msg + " error : "
+ ackDet.getText().getContent());
if (PixManagerConstants.PIX_ADD.equalsIgnoreCase(msg)) {
pixMgrBean.setAddMessage(msg + " Failure! "
+ ackDet.getText().getContent());
} else if (PixManagerConstants.PIX_UPDATE
.equalsIgnoreCase(msg)) {
pixMgrBean.setUpdateMessage(msg + " Failure! "
+ ackDet.getText().getContent());
}
break;
}
} else {
if (PixManagerConstants.PIX_ADD.equalsIgnoreCase(msg)) {
pixMgrBean.setAddMessage(msg + " Failure! ");
} else if (PixManagerConstants.PIX_UPDATE.equalsIgnoreCase(msg)) {
pixMgrBean.setUpdateMessage(msg + " Failure! ");
}
}
}
}
/**
* Gets the general exp message.
*
* @param e
* the e
* @param pixMgrBean
* the pix mgr bean
* @param msg
* the msg
* @return the general exp message
*/
protected void getGeneralExpMessage(Exception e, PixManagerBean pixMgrBean,
String msg) {
// Expect the unexpected
logger.error("Unexpected exception", e);
// Add error
logger.error("error",
"Query Failure! Server error! A unexpected error has occured");
final String errMsg = " Failure! Server error! A unexpected error has occured";
logger.error("exception: " + e.getCause());
logger.error("detail message: " + e.getMessage());
if (PixManagerConstants.PIX_ADD.equalsIgnoreCase(msg)) {
pixMgrBean.setAddMessage(msg + errMsg);
} else if (PixManagerConstants.PIX_QUERY.equalsIgnoreCase(msg)) {
pixMgrBean.setQueryMessage(msg + errMsg);
} else if (PixManagerConstants.PIX_UPDATE.equalsIgnoreCase(msg)) {
pixMgrBean.setUpdateMessage(msg + errMsg);
}
}
/**
* Gets the query message.
*
* @param response
* the response
* @param pixMgrBean
* the pix mgr bean
* @return the query message
*/
@SuppressWarnings("unchecked")
protected void getQueryMessage(PRPAIN201310UV02 response,
PixManagerBean pixMgrBean) {
// The message has been sent
// But it doesn't mean we're subscribed successfully
logger.debug("response ack code:" + response.getAcceptAckCode());
logger.debug("response type id: " + response.getTypeId());
final JXPathContext context = JXPathContext.newContext(response);
final Iterator<MCCIMT000300UV01Acknowledgement> ackmntList = context
.iterate("/acknowledgement");
while (ackmntList.hasNext()) {
final MCCIMT000300UV01Acknowledgement ackmnt = ackmntList.next();
if (ackmnt.getTypeCode().getCode().equals("AA")) {
final StringBuffer queryMsg = new StringBuffer(
"Query Success! ");
final Map<String, String> idMap = new HashMap<String, String>();
final Iterator<PRPAMT201307UV02PatientIdentifier> pidList = context
.iterate("/controlActProcess/queryByParameter/value/parameterList/patientIdentifier");
while (pidList.hasNext()) {
final PRPAMT201307UV02PatientIdentifier pid = pidList
.next();
final List<II> ptIdList = pid.getValue();
for (final II ptId : ptIdList) {
queryMsg.append(" Given PID: " + ptId.getExtension());
queryMsg.append(" Given UID: " + ptId.getRoot());
queryMsg.append("\t");
}
}
final Iterator<II> ptIdList = context
.iterate("/controlActProcess/subject[1]/registrationEvent/subject1[typeCode='SBJ']/patient[classCode='PAT']/id");
while (ptIdList.hasNext()) {
final II pId = ptIdList.next();
idMap.put(pId.getRoot(), pId.getExtension());
// System.out.println("Requested UID: " + pId.getRoot());
// System.out.println("Requested PID: " +
// pId.getExtension());
// queryMsg.append(" Requested PID: " + pId.getExtension());
// queryMsg.append(" Requested UID: " + pId.getRoot());
// queryMsg.append("\t");
}
pixMgrBean.setQueryMessage(queryMsg.toString());
pixMgrBean.setQueryIdMap(idMap);
break;
} else if (ackmnt.getTypeCode().getCode().equals("AE")) {
final List<MCCIMT000300UV01AcknowledgementDetail> ackmntDetList = ackmnt
.getAcknowledgementDetail();
for (final MCCIMT000300UV01AcknowledgementDetail ackDet : ackmntDetList) {
logger.error("Query Failure! "
+ ackDet.getText().getContent());
pixMgrBean.setQueryMessage("Query Failure! "
+ ackDet.getText().getContent());
pixMgrBean.setQueryIdMap(null);
break;
}
} else {
pixMgrBean.setQueryMessage("Query Failure! ");
pixMgrBean.setQueryIdMap(null);
}
}
}
/**
* Gets the pix mgr bean.
*
* @return the pix mgr bean
*/
PixManagerBean getPixMgrBean() {
return pixMgrBean;
}
/**
* Sets the pix mgr bean.
*
* @param pixMgrBean
* the new pix mgr bean
*/
void setPixMgrBean(PixManagerBean pixMgrBean) {
this.pixMgrBean = pixMgrBean;
}
private MCCIIN000002UV01 pidFeed(PixOperation pixOperation, String c32xml) {
MCCIIN000002UV01 response = null;
final PixOperation pixQuery = PixOperation.QUERY;
String msg = null;
try {
String hl7v3Xml = pixManagerTransformService.getPixXml(pixQuery,
c32xml);
final PixManagerBean pixManagerBean = queryPerson(hl7v3Xml);
final Map<String, String> queryMap = pixManagerBean.getQueryIdMap();
if (null != queryMap) {
// person already available in EMPI get global identifier
// id(EID)
// get piadd hl7v3 xml
hl7v3Xml = pixManagerTransformService.getPixXml(pixOperation,
c32xml);
// get Eid Values
final String eid = queryMap
.get(PixManagerConstants.GLOBAL_DOMAIN_ID);
msg = xdsbRegistryGetter.pidFeed(pixOperation, hl7v3Xml, eid,
PixManagerConstants.GLOBAL_DOMAIN_ID);
response = marshaller.unmarshalFromXml(MCCIIN000002UV01.class,
msg);
}
} catch (final Throwable e) {
// Expect the unexpected
logger.error("Unexpected exception", e);
// Add error
logger.error("error",
"Query Failure! Server error! A unexpected error has occured");
throw new AcsShowCaseException(e.toString(), e);
}
return response;
}
}