/*******************************************************************************
* 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.acs.xdsb.registry.wsclient.adapter;
import gov.samhsa.acs.common.exception.DS4PException;
import gov.samhsa.acs.common.log.AcsLogger;
import gov.samhsa.acs.common.log.AcsLoggerFactory;
import gov.samhsa.acs.common.tool.DocumentAccessor;
import gov.samhsa.acs.common.tool.DocumentXmlConverter;
import gov.samhsa.acs.common.tool.SimpleMarshaller;
import gov.samhsa.acs.common.tool.exception.DocumentAccessorException;
import gov.samhsa.acs.common.tool.exception.DocumentXmlConverterException;
import gov.samhsa.acs.common.tool.exception.SimpleMarshallerException;
import gov.samhsa.acs.xdsb.common.XdsbDocumentReference;
import gov.samhsa.acs.xdsb.common.XdsbDocumentType;
import gov.samhsa.acs.xdsb.registry.wsclient.XdsbRegistryWebServiceClient;
import gov.samhsa.acs.xdsb.registry.wsclient.exception.XdsbRegistryAdapterException;
import ihe.iti.xds_b._2007.RetrieveDocumentSetRequest;
import ihe.iti.xds_b._2007.RetrieveDocumentSetRequest.DocumentRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import oasis.names.tc.ebxml_regrep.xsd.query._3.AdhocQueryRequest;
import oasis.names.tc.ebxml_regrep.xsd.query._3.AdhocQueryResponse;
import oasis.names.tc.ebxml_regrep.xsd.query._3.ResponseOptionType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.AdhocQueryType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.SlotType1;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.ValueListType;
import org.springframework.util.Assert;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* The Class XdsbRegistryAdapter.
*/
public class XdsbRegistryAdapter {
/** The logger. */
private final AcsLogger logger = AcsLoggerFactory
.getLogger(this.getClass());
// Services
/** The xdsb registry. */
private XdsbRegistryWebServiceClient xdsbRegistry;
/** The response filter. */
private AdhocQueryResponseFilter responseFilter;
/** The marshaller. */
private SimpleMarshaller marshaller;
/** The document xml converter. */
private DocumentXmlConverter documentXmlConverter;
/** The document accessor. */
private DocumentAccessor documentAccessor;
// Supported XDS.b Format Codes
/** The Constant FORMAT_CODE_CLINICAL_DOCUMENT. */
public static final String FORMAT_CODE_CLINICAL_DOCUMENT = "'2.16.840.1.113883.10.20.1^^HITSP'";
/** The Constant FORMAT_CODE_PRIVACY_CONSENT. */
public static final String FORMAT_CODE_PRIVACY_CONSENT = "'1.3.6.1.4.1.19376.1.5.3.1.1.7^^IHE BPPC'";
// AdhocQuery Slot Names
/** The Constant SLOT_NAME_XDS_DOCUMENT_ENTRY_FORMAT_CODE. */
public static final String SLOT_NAME_XDS_DOCUMENT_ENTRY_FORMAT_CODE = "$XDSDocumentEntryFormatCode";
/** The Constant SLOT_NAME_XDS_DOCUMENT_ENTRY_PATIENT_ID. */
public static final String SLOT_NAME_XDS_DOCUMENT_ENTRY_PATIENT_ID = "$XDSDocumentEntryPatientId";
/** The Constant SLOT_NAME_XDS_DOCUMENT_ENTRYSTATUS. */
public static final String SLOT_NAME_XDS_DOCUMENT_ENTRY_STATUS = "$XDSDocumentEntryStatus";
// UUIDs
/** The Constant UUID_XDS_DOCUMENTENTRY. */
public static final String UUID_XDS_DOCUMENTENTRY = "urn:uuid:7edca82f-054d-47f2-a032-9b2a5b5186c1";
/** The Constant UUID_XDS_DOCUMENTENTRY_UNIQUEID. */
public static final String UUID_XDS_DOCUMENTENTRY_UNIQUEID = "urn:uuid:2e82c1f6-a085-4c72-9da3-8640a32e42ab";
/** The Constant UUID_XDS_DOCUMENTENTRY_AUTHOR. */
public static final String UUID_XDS_DOCUMENTENTRY_AUTHOR = "urn:uuid:93606bcf-9494-43ec-9b4e-a7748d1a838d";
/** The Constant UUID_XDS_SUBMISSION_SET_UNIQUEID. */
public static final String UUID_XDS_SUBMISSION_SET_UNIQUEID = "urn:uuid:96fdda7c-d067-4183-912e-bf5ee74998a8";
// Stored Queries
// Find Submission Sets
/** The Constant STORED_QUERY_FIND_SUBMISSION_SETS. */
private static final String STORED_QUERY_FIND_SUBMISSION_SETS = "<ns3:AdhocQueryRequest xmlns:ns2=\"urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0\" xmlns:ns3=\"urn:oasis:names:tc:ebxml-regrep:xsd:query:3.0\" xmlns:ns4=\"urn:oasis:names:tc:ebxml-regrep:xsd:rs:3.0\"><ns3:ResponseOption returnComposedObjects=\"true\" returnType=\"LeafClass\"/><ns2:AdhocQuery id=\"urn:uuid:f26abbcb-ac74-4422-8a30-edb644bbc1a9\"><ns2:Slot name=\"$XDSSubmissionSetPatientId\"><ns2:ValueList><ns2:Value>@XDSSubmissionSetPatientId</ns2:Value></ns2:ValueList></ns2:Slot><ns2:Slot name=\"$XDSSubmissionSetAuthorPerson\"><ns2:ValueList><ns2:Value>@XDSSubmissionSetAuthorPerson</ns2:Value></ns2:ValueList></ns2:Slot><ns2:Slot name=\"$XDSSubmissionSetStatus\"><ns2:ValueList><ns2:Value>('urn:oasis:names:tc:ebxml-regrep:StatusType:Approved')</ns2:Value></ns2:ValueList></ns2:Slot></ns2:AdhocQuery></ns3:AdhocQueryRequest>";
/** The Constant PARAM_XDS_SUBMISSION_SET_PATIENT_ID. */
private static final String PARAM_XDS_SUBMISSION_SET_PATIENT_ID = "@XDSSubmissionSetPatientId";
/** The Constant PARAM_XDS_SUBMISSION_SET_AUTHOR_PERSON. */
private static final String PARAM_XDS_SUBMISSION_SET_AUTHOR_PERSON = "@XDSSubmissionSetAuthorPerson";
// Get Submission Set and Contents
/** The Constant STORED_QUERY_GET_SUBMISSION_SET_AND_CONTENTS. */
private static final String STORED_QUERY_GET_SUBMISSION_SET_AND_CONTENTS = "<ns3:AdhocQueryRequest xmlns:ns2=\"urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0\" xmlns:ns3=\"urn:oasis:names:tc:ebxml-regrep:xsd:query:3.0\" xmlns:ns4=\"urn:oasis:names:tc:ebxml-regrep:xsd:rs:3.0\"><ns3:ResponseOption returnComposedObjects=\"true\" returnType=\"LeafClass\"/><ns2:AdhocQuery id=\"urn:uuid:e8e3cb2c-e39c-46b9-99e4-c12f57260b83\"><ns2:Slot name=\"$XDSSubmissionSetUniqueId\"><ns2:ValueList><!-- This operation only works for the first value, do not pass multiple values here.--><ns2:Value>'@XDSSubmissionSetUniqueId'</ns2:Value></ns2:ValueList></ns2:Slot></ns2:AdhocQuery></ns3:AdhocQueryRequest>";
/** The Constant PARAM_XDS_SUBMISSION_SET_UNIQUEID. */
private static final String PARAM_XDS_SUBMISSION_SET_UNIQUEID = "@XDSSubmissionSetUniqueId";
/** The Constant SUBMISSION_SET_STATUS_DEPRECATED. */
private static final String SUBMISSION_SET_STATUS_DEPRECATED = "urn:oasis:names:tc:ebxml-regrep:StatusType:Deprecated";
/**
* Instantiates a new xdsb registry adapter.
*
* @param xdsbRegistry
* the xdsb registry
* @param responseFilter
* the response filter
* @param marshaller
* the marshaller
* @param documentXmlConverter
* the document xml converter
* @param documentAccessor
* the document accessor
*/
public XdsbRegistryAdapter(XdsbRegistryWebServiceClient xdsbRegistry,
AdhocQueryResponseFilter responseFilter,
SimpleMarshaller marshaller,
DocumentXmlConverter documentXmlConverter,
DocumentAccessor documentAccessor) {
this.xdsbRegistry = xdsbRegistry;
this.responseFilter = responseFilter;
this.marshaller = marshaller;
this.documentXmlConverter = documentXmlConverter;
this.documentAccessor = documentAccessor;
}
/**
* Registry stored query (direct call to the XDS.b registry service).
*
* @param adhocQueryRequest
* the adhoc query request
* @return the adhoc query response
*/
public AdhocQueryResponse registryStoredQuery(
AdhocQueryRequest adhocQueryRequest) {
return xdsbRegistry.registryStoredQuery(adhocQueryRequest);
}
/**
* Registry stored query (indirect call to the XDS.b registry service with a
* simplified interface).
*
* @param patientId
* the patient id
* @param domainId
* the domain id
* @param authorId
* the author id
* @param xdsbDocumentType
* the xdsb document type
* @param serviceTimeAware
* the service time aware
* @param messageId
* the message id
* @return the adhoc query response
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
public AdhocQueryResponse registryStoredQuery(String patientId,
String domainId, String authorId,
XdsbDocumentType xdsbDocumentType, boolean serviceTimeAware,
String messageId) throws XdsbRegistryAdapterException {
String patientUniqueId = getPatientUniqueId(patientId, domainId);
return registryStoredQuery(patientUniqueId, authorId, xdsbDocumentType,
serviceTimeAware, messageId);
}
/**
* Registry stored query.
*
* @param patientUniqueId
* the patient unique id
* @param authorNPI
* the author npi
* @param xdsbDocumentType
* the xdsb document type
* @param serviceTimeAware
* the service time aware
* @param messageId
* the message id
* @return the adhoc query response
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
public AdhocQueryResponse registryStoredQuery(String patientUniqueId,
String authorNPI, XdsbDocumentType xdsbDocumentType,
boolean serviceTimeAware, String messageId)
throws XdsbRegistryAdapterException {
// Create a query request to search by patient unique id
AdhocQueryRequest registryStoredQuery = createRegistryStoredQueryByPatientId(
patientUniqueId, xdsbDocumentType, serviceTimeAware, messageId);
return registryStoredQueryFilterByAuthorNPI(registryStoredQuery,
authorNPI, messageId);
}
/**
* Registry stored query.
*
* @param req
* the req
* @param authorNPI
* the author npi
* @param messageId
* the message id
* @return the adhoc query response
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
public AdhocQueryResponse registryStoredQuery(AdhocQueryRequest req,
String authorNPI, String messageId)
throws XdsbRegistryAdapterException {
try {
return registryStoredQueryFilterByAuthorNPI(req, authorNPI,
messageId);
} catch (Throwable t) {
throw new XdsbRegistryAdapterException(t);
}
}
/**
* Find deprecated document unique ids.
*
* @param submissionSetPatientId
* the submission set patient id
* @param submissionSetAuthorPerson
* the submission set author person
* @param messageId
* the message id
* @return the list
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
public List<String> findDeprecatedDocumentUniqueIds(
String submissionSetPatientId, String submissionSetAuthorPerson,
String messageId) throws XdsbRegistryAdapterException {
submissionSetPatientId = submissionSetPatientId.replaceAll("&(?!amp;)",
"&");
submissionSetAuthorPerson = submissionSetAuthorPerson.replaceAll(
"&(?!amp;)", "&");
List<String> deprecatedDocumentUniqueIds = new LinkedList<String>();
AdhocQueryResponse findSubmissionSetsResponse = findSubmissionSets(
submissionSetPatientId, submissionSetAuthorPerson);
List<String> submissionSetUniqueIds = extractSubmissionSetUniqueIds(findSubmissionSetsResponse);
for (String submissionSetUniqueId : submissionSetUniqueIds) {
AdhocQueryResponse getSubmissionSetAndContentsResponse = getSubmissionSetAndContents(
submissionSetUniqueId, messageId);
String deprecatedDocumentUniqueId = extractDeprecatedDocumentUniqueId(
getSubmissionSetAndContentsResponse, messageId);
if (deprecatedDocumentUniqueId != null) {
deprecatedDocumentUniqueIds.add(deprecatedDocumentUniqueId);
}
}
return deprecatedDocumentUniqueIds;
}
/**
* Find submission sets.
*
* @param submissionSetPatientId
* the submission set patient id
* @param submissionSetAuthorPerson
* the submission set author person
* @return the adhoc query response
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
public AdhocQueryResponse findSubmissionSets(String submissionSetPatientId,
String submissionSetAuthorPerson)
throws XdsbRegistryAdapterException {
Assert.notNull(submissionSetPatientId);
Assert.notNull(submissionSetAuthorPerson);
AdhocQueryRequest findSubmissionSetsRequest = createFindSubmissionSetsRequest(
submissionSetPatientId, submissionSetAuthorPerson);
return registryStoredQuery(findSubmissionSetsRequest);
}
/**
* Gets the submission set and contents.
*
* @param submissionSetUniqueId
* the submission set unique id
* @param messageId
* the message id
* @return the gets the submission set and contents
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
public AdhocQueryResponse getSubmissionSetAndContents(
String submissionSetUniqueId, String messageId)
throws XdsbRegistryAdapterException {
// Invoke this method for each submissionSetId at a time. This stored
// query doesn't support retrieval of multiple submission sets, do not
// try to implement it.
Assert.notNull(submissionSetUniqueId);
AdhocQueryRequest getSubmissionSetAndContentsRequest = createGetSubmissionSetAndContentsRequest(
submissionSetUniqueId, messageId);
return registryStoredQuery(getSubmissionSetAndContentsRequest);
}
/**
* Extract submission set unique ids.
*
* @param response
* the response
* @return the list
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
public List<String> extractSubmissionSetUniqueIds(
AdhocQueryResponse response) throws XdsbRegistryAdapterException {
try {
List<String> submissionSetUniqueIdList = new LinkedList<String>();
String responseXml = this.marshaller.marshal(response);
Document responseDoc = this.documentXmlConverter
.loadDocument(responseXml);
String xPathExpr = "//rim:ExternalIdentifier[@identificationScheme='$']/@value";
NodeList nodeList = this.documentAccessor.getNodeList(responseDoc,
xPathExpr.replace("$", UUID_XDS_SUBMISSION_SET_UNIQUEID));
for (int i = 0; i < nodeList.getLength(); i++) {
submissionSetUniqueIdList.add(nodeList.item(i).getNodeValue());
}
return submissionSetUniqueIdList;
} catch (SimpleMarshallerException | DocumentAccessorException e) {
throw new XdsbRegistryAdapterException(e);
}
}
/**
* Extract deprecated document unique id.
*
* @param response
* the response
* @param messageId
* the message id
* @return the string
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
public String extractDeprecatedDocumentUniqueId(
AdhocQueryResponse response, String messageId)
throws XdsbRegistryAdapterException {
try {
String responseXml = this.marshaller.marshal(response);
Document responseDoc = this.documentXmlConverter
.loadDocument(responseXml);
// Extract documentUniqueId if there is an association in the
// submission
// set with a NewStatus slot having SUBMISSION_SET_STATUS_DEPRECATED
// value. Return null, if there is not any.
StringBuilder builder = new StringBuilder();
builder.append("//rim:Association[descendant::rim:Slot[@name='NewStatus']][descendant::rim:Value[.='");
builder.append(SUBMISSION_SET_STATUS_DEPRECATED);
builder.append("']]/preceding-sibling::rim:ExtrinsicObject[@objectType='");
builder.append(UUID_XDS_DOCUMENTENTRY);
builder.append("']/descendant::rim:ExternalIdentifier[@identificationScheme='");
builder.append(UUID_XDS_DOCUMENTENTRY_UNIQUEID);
builder.append("']/@value");
String xPathExpr = builder.toString();
Node node = this.documentAccessor.getNode(responseDoc, xPathExpr);
if (node == null) {
return null;
} else {
return node.getNodeValue();
}
} catch (SimpleMarshallerException | DocumentAccessorException e) {
logger.error(messageId, e.getMessage());
throw new XdsbRegistryAdapterException(e.getMessage(), e);
}
}
/**
* Extract XDS.b document reference list.
*
* @param adhocQueryResponse
* the adhoc query response
* @return the list of XdsbDocumentReference objects having documentUniqueId
* and repositoryId pairs to retrieve the documents
* @throws Exception
* the exception
* @throws Throwable
* the throwable
*/
public List<XdsbDocumentReference> extractXdsbDocumentReferenceList(
AdhocQueryResponse adhocQueryResponse) throws Exception, Throwable {
String adhocQueryResponseXmlString = marshaller
.marshal(adhocQueryResponse);
Document doc = documentXmlConverter
.loadDocument(adhocQueryResponseXmlString);
// Scan the document ExtrinsicObject elements
NodeList extrinsicObjects = doc.getElementsByTagName("ExtrinsicObject");
// Temporary storage for documentUniqueIds and repositryIds
Map<Integer, String> documentUniqueIdMap = new HashMap<Integer, String>();
Map<Integer, String> repositoryUniqueIdMap = new HashMap<Integer, String>();
// For each ExtrinsicObject
for (int i = 0; i < extrinsicObjects.getLength(); i++) {
Node extrinsicObject = extrinsicObjects.item(i);
NodeList extrinsicObjectItems = extrinsicObject.getChildNodes();
// For each element of ExtrinsicObject
for (int j = 0; j < extrinsicObjectItems.getLength(); j++) {
Node extrinsicObjectItem = extrinsicObjectItems.item(j);
// If the element is ExternalIdentifier with
// a XDSDocumentEntry UniqueId
if ("ExternalIdentifier".equals(extrinsicObjectItem
.getNodeName())
&& UUID_XDS_DOCUMENTENTRY_UNIQUEID
.equals(extrinsicObjectItem.getAttributes()
.getNamedItem("identificationScheme")
.getNodeValue())) {
// Get the value of UniqueId and store in temporary map
documentUniqueIdMap.put(i, extrinsicObjectItem
.getAttributes().getNamedItem("value")
.getNodeValue());
}
// If the element is a Slot with repositoryUniqueId
if ("Slot".equals(extrinsicObjectItem.getNodeName())
&& "repositoryUniqueId".equals(extrinsicObjectItem
.getAttributes().getNamedItem("name")
.getNodeValue())) {
// Get the value of repositoryUniqueId and store in
// temporary map
repositoryUniqueIdMap.put(i, extrinsicObjectItem
.getChildNodes().item(0).getChildNodes().item(0)
.getTextContent());
}
}
}
// Combine the maps into a list of XdsbDocumentReference
Set<Integer> keys = documentUniqueIdMap.keySet();
List<XdsbDocumentReference> repositoryAndDocumentUniqueIdList = new LinkedList<XdsbDocumentReference>();
for (Integer key : keys) {
XdsbDocumentReference xdsbDocumentReference = new XdsbDocumentReference(
documentUniqueIdMap.get(key),
repositoryUniqueIdMap.get(key));
repositoryAndDocumentUniqueIdList.add(xdsbDocumentReference);
}
return repositoryAndDocumentUniqueIdList;
}
/**
* Extract xdsb document reference list as retrieve document set request.
*
* @param adhocQueryResponse
* the adhoc query response
* @return the retrieve document set request
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
public RetrieveDocumentSetRequest extractXdsbDocumentReferenceListAsRetrieveDocumentSetRequest(
AdhocQueryResponse adhocQueryResponse)
throws XdsbRegistryAdapterException {
String adhocQueryResponseXmlString;
try {
adhocQueryResponseXmlString = marshaller
.marshal(adhocQueryResponse);
Document doc = documentXmlConverter
.loadDocument(adhocQueryResponseXmlString);
// Scan the document ExtrinsicObject elements
NodeList extrinsicObjects = doc
.getElementsByTagName("ExtrinsicObject");
// Temporary storage for documentUniqueIds and repositryIds
Map<Integer, String> documentUniqueIdMap = new HashMap<Integer, String>();
Map<Integer, String> repositoryUniqueIdMap = new HashMap<Integer, String>();
// For each ExtrinsicObject
for (int i = 0; i < extrinsicObjects.getLength(); i++) {
Node extrinsicObject = extrinsicObjects.item(i);
NodeList extrinsicObjectItems = extrinsicObject.getChildNodes();
// For each element of ExtrinsicObject
for (int j = 0; j < extrinsicObjectItems.getLength(); j++) {
Node extrinsicObjectItem = extrinsicObjectItems.item(j);
// If the element is ExternalIdentifier with
// a XDSDocumentEntry UniqueId
if ("ExternalIdentifier".equals(extrinsicObjectItem
.getNodeName())
&& UUID_XDS_DOCUMENTENTRY_UNIQUEID
.equals(extrinsicObjectItem
.getAttributes()
.getNamedItem(
"identificationScheme")
.getNodeValue())) {
// Get the value of UniqueId and store in temporary map
documentUniqueIdMap.put(i, extrinsicObjectItem
.getAttributes().getNamedItem("value")
.getNodeValue());
}
// If the element is a Slot with repositoryUniqueId
if ("Slot".equals(extrinsicObjectItem.getNodeName())
&& "repositoryUniqueId".equals(extrinsicObjectItem
.getAttributes().getNamedItem("name")
.getNodeValue())) {
// Get the value of repositoryUniqueId and store in
// temporary map
repositoryUniqueIdMap.put(i, extrinsicObjectItem
.getChildNodes().item(0).getChildNodes()
.item(0).getTextContent());
}
}
}
// Combine the maps into a list of XdsbDocumentReference
Set<Integer> keys = documentUniqueIdMap.keySet();
RetrieveDocumentSetRequest retrieveDocumentSetRequest = new RetrieveDocumentSetRequest();
List<DocumentRequest> documentRequestList = retrieveDocumentSetRequest
.getDocumentRequest();
for (Integer key : keys) {
XdsbDocumentReference xdsbDocumentReference = new XdsbDocumentReference(
documentUniqueIdMap.get(key),
repositoryUniqueIdMap.get(key));
documentRequestList.add(xdsbDocumentReference);
}
return retrieveDocumentSetRequest;
} catch (SimpleMarshallerException | DocumentXmlConverterException e) {
throw new XdsbRegistryAdapterException(e);
}
}
/**
* Extract patient id.
*
* @param req
* the req
* @return the string
*/
public String extractPatientId(AdhocQueryRequest req) {
return extractSlotValue(req, SLOT_NAME_XDS_DOCUMENT_ENTRY_PATIENT_ID);
}
/**
* Extract format code.
*
* @param req
* the req
* @return the string
*/
public String extractFormatCode(AdhocQueryRequest req) {
return extractSlotValue(req, SLOT_NAME_XDS_DOCUMENT_ENTRY_FORMAT_CODE);
}
/**
* Extract response option return type.
*
* @param req
* the req
* @return the string
*/
public String extractResponseOptionReturnType(AdhocQueryRequest req) {
return req.getResponseOption().getReturnType();
}
/**
* Extract document entry status.
*
* @param req
* the req
* @return the string
*/
public String extractDocumentEntryStatus(AdhocQueryRequest req) {
return extractSlotValue(req, SLOT_NAME_XDS_DOCUMENT_ENTRY_STATUS);
}
/**
* Gets the patient unique id.
*
* @param patientId
* the patient id
* @param domainId
* the domain id
* @return the patient unique id
*/
public String getPatientUniqueId(String patientId, String domainId) {
StringBuilder builder = new StringBuilder();
builder.append("'");
builder.append(patientId);
builder.append("^^^&");
builder.append(domainId);
builder.append("&ISO'");
return builder.toString();
}
/**
* Creates the find submission sets request.
*
* @param submissionSetPatientId
* the submission set patient id
* @param submissionSetAuthorPerson
* the submission set author person
* @return the adhoc query request
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
AdhocQueryRequest createFindSubmissionSetsRequest(
String submissionSetPatientId, String submissionSetAuthorPerson)
throws XdsbRegistryAdapterException {
try {
AdhocQueryRequest findSubmissionSetsRequest = this.marshaller
.unmarshalFromXml(
AdhocQueryRequest.class,
STORED_QUERY_FIND_SUBMISSION_SETS.replace(
PARAM_XDS_SUBMISSION_SET_PATIENT_ID,
submissionSetPatientId).replace(
PARAM_XDS_SUBMISSION_SET_AUTHOR_PERSON,
submissionSetAuthorPerson));
return findSubmissionSetsRequest;
} catch (SimpleMarshallerException e) {
throw new XdsbRegistryAdapterException(e);
}
}
/**
* Creates the get submission set and contents request.
*
* @param submissionSetUniqueId
* the submission set unique id
* @param messageId
* the message id
* @return the adhoc query request
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
AdhocQueryRequest createGetSubmissionSetAndContentsRequest(
String submissionSetUniqueId, String messageId)
throws XdsbRegistryAdapterException {
try {
AdhocQueryRequest getSubmissionSetAndContentsRequest = this.marshaller
.unmarshalFromXml(AdhocQueryRequest.class,
STORED_QUERY_GET_SUBMISSION_SET_AND_CONTENTS
.replace(PARAM_XDS_SUBMISSION_SET_UNIQUEID,
submissionSetUniqueId));
return getSubmissionSetAndContentsRequest;
} catch (SimpleMarshallerException e) {
logger.error(messageId, e.getMessage());
throw new XdsbRegistryAdapterException(e);
}
}
/**
* Creates the registry stored query by patient id.
*
* @param patientUniqueId
* the patient unique id
* @param xdsbDocumentType
* the xdsb document type
* @param serviceTimeAware
* the service time aware
* @param messageId
* the message id
* @return the adhoc query request
*/
AdhocQueryRequest createRegistryStoredQueryByPatientId(
String patientUniqueId, XdsbDocumentType xdsbDocumentType,
boolean serviceTimeAware, String messageId) {
// Create registryStoredQuery
AdhocQueryRequest registryStoredQuery = new AdhocQueryRequest();
// Set response option to return all metadata of the documents in the
// response
setResponseOptionToGetAllMetadata(registryStoredQuery);
// Create a query type that will find documents by given patient id
AdhocQueryType adhocQueryType = createFindDocumentsByPatientIdQueryType();
registryStoredQuery.setAdhocQuery(adhocQueryType);
// Modify query type
// add patient id (will only return document references of the given
// patient id)
addPatientId(adhocQueryType, patientUniqueId);
// add approved document entry status (will only return document
// references with approved status)
addEntryStatusApproved(adhocQueryType);
// add format code (will only return document references for the given
// supported document type)
addFormatCode(adhocQueryType, xdsbDocumentType, messageId);
if (serviceTimeAware) {
// add service time constraint (will only return the document
// references within valid service start/end time)
addServiceTimeConstraint(adhocQueryType);
}
return registryStoredQuery;
}
/**
* Creates the find documents by patient id query type.
*
* @return the adhoc query type
*/
AdhocQueryType createFindDocumentsByPatientIdQueryType() {
AdhocQueryType adhocQueryType = new AdhocQueryType();
// FindDocuments by patientId
adhocQueryType.setId("urn:uuid:14d4debf-8f97-4251-9a74-a90016b0af0d");
return adhocQueryType;
}
/**
* Sets the response option to get all metadata.
*
* @param registryStoredQuery
* the new response option to get all metadata
*/
void setResponseOptionToGetAllMetadata(AdhocQueryRequest registryStoredQuery) {
ResponseOptionType responseOptionType = new ResponseOptionType();
responseOptionType.setReturnComposedObjects(true);
responseOptionType.setReturnType("LeafClass");
registryStoredQuery.setResponseOption(responseOptionType);
}
/**
* Adds the patient id.
*
* @param adhocQueryType
* the adhoc query type
* @param patientUniqueId
* the patient unique id
*/
void addPatientId(AdhocQueryType adhocQueryType, String patientUniqueId) {
if (!patientUniqueId.startsWith("'") || !patientUniqueId.endsWith("'")) {
patientUniqueId = patientUniqueId.replace("'", "");
StringBuilder builder = new StringBuilder();
builder.append("'");
builder.append(patientUniqueId);
builder.append("'");
patientUniqueId = builder.toString();
}
SlotType1 patientIdSlotType = new SlotType1();
patientIdSlotType.setName(SLOT_NAME_XDS_DOCUMENT_ENTRY_PATIENT_ID);
ValueListType patientIdValueListType = new ValueListType();
patientIdValueListType.getValue().add(patientUniqueId); // PatientId
patientIdSlotType.setValueList(patientIdValueListType);
adhocQueryType.getSlot().add(patientIdSlotType);
}
/**
* Adds the entry status approved.
*
* @param adhocQueryType
* the adhoc query type
*/
void addEntryStatusApproved(AdhocQueryType adhocQueryType) {
SlotType1 statusSlotType = new SlotType1();
statusSlotType.setName("$XDSDocumentEntryStatus");
ValueListType statusValueListType = new ValueListType();
statusValueListType.getValue().add(
"('urn:oasis:names:tc:ebxml-regrep:StatusType:Approved')");
statusSlotType.setValueList(statusValueListType);
adhocQueryType.getSlot().add(statusSlotType);
}
/**
* Adds the format code.
*
* @param adhocQueryType
* the adhoc query type
* @param xdsbDocumentType
* the xdsb document type
* @param messageId
* the message id
*/
void addFormatCode(AdhocQueryType adhocQueryType,
XdsbDocumentType xdsbDocumentType, String messageId) {
SlotType1 formatCodeSlotType = new SlotType1();
formatCodeSlotType.setName(SLOT_NAME_XDS_DOCUMENT_ENTRY_FORMAT_CODE);
ValueListType formatCodeValueListType = new ValueListType();
if (xdsbDocumentType.equals(XdsbDocumentType.CLINICAL_DOCUMENT)) {
formatCodeValueListType.getValue().add(
FORMAT_CODE_CLINICAL_DOCUMENT);
} else if (xdsbDocumentType.equals(XdsbDocumentType.PRIVACY_CONSENT)) {
formatCodeValueListType.getValue().add(FORMAT_CODE_PRIVACY_CONSENT);
} else {
logger.error(messageId, "Unsupported XDS.b document format code");
throw new DS4PException("Unsupported XDS.b document format code");
}
formatCodeSlotType.setValueList(formatCodeValueListType);
adhocQueryType.getSlot().add(formatCodeSlotType);
}
/**
* Adds the service time constraint.
*
* @param adhocQueryType
* the adhoc query type
*/
void addServiceTimeConstraint(AdhocQueryType adhocQueryType) {
String currentTime = getCurrentTime();
// Set upper value of XDSDocumentEntry serviceStartTime
SlotType1 serviceStartSlotType = new SlotType1();
serviceStartSlotType.setName("$XDSDocumentEntryServiceStartTimeTo");
ValueListType serviceStartValueListType = new ValueListType();
serviceStartValueListType.getValue().add(currentTime);
serviceStartSlotType.setValueList(serviceStartValueListType);
adhocQueryType.getSlot().add(serviceStartSlotType);
// Set lower value of XDSDocumentEntry serviceStopTime
SlotType1 serviceStopSlotType = new SlotType1();
serviceStopSlotType.setName("$XDSDocumentEntryServiceStopTimeFrom");
ValueListType serviceStopValueListType = new ValueListType();
serviceStopValueListType.getValue().add(currentTime);
serviceStopSlotType.setValueList(serviceStopValueListType);
adhocQueryType.getSlot().add(serviceStopSlotType);
}
/**
* Registry stored query filter by author npi.
*
* @param req
* the req
* @param authorNPI
* the author npi
* @param messageId
* the message id
* @return the adhoc query response
* @throws XdsbRegistryAdapterException
* the xdsb registry adapter exception
*/
private AdhocQueryResponse registryStoredQueryFilterByAuthorNPI(
AdhocQueryRequest req, String authorNPI, String messageId)
throws XdsbRegistryAdapterException {
try {
// Query Response
AdhocQueryResponse adhocQueryResponse = registryStoredQuery(req);
if (authorNPI != null && !"".equals(authorNPI)) {
adhocQueryResponse = responseFilter.filterByAuthor(
adhocQueryResponse, authorNPI);
}
logger.debug(messageId, marshaller.marshal(adhocQueryResponse));
return adhocQueryResponse;
} catch (SimpleMarshallerException e) {
throw new XdsbRegistryAdapterException(e);
}
}
/**
* Gets the current time.
*
* @return the current time
*/
private String getCurrentTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
return sdf.format(new Date());
}
/**
* Extract slot value.
*
* @param req
* the req
* @param slotName
* the slot name
* @return the string
*/
private String extractSlotValue(AdhocQueryRequest req, String slotName) {
List<SlotType1> slots = req.getAdhocQuery().getSlot();
for (SlotType1 slot : slots) {
if (slotName.equals(slot.getName())) {
return slot.getValueList().getValue().get(0);
}
}
return null;
}
}