diff --git a/.gitignore b/.gitignore
index 427e890..430c527 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,12 @@ target
.DS_Store
# Log Files
-*.log
\ No newline at end of file
+*.log
+
+# test files
+api/null/*
+null/*
+
+#vs Code
+.vscode/*
+api/id_file
diff --git a/api/pom.xml b/api/pom.xml
index c9ef90b..8f8a098 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -18,6 +18,7 @@
org.openmrs.module
fhir2-api
+ ${fhirModuleVersion}
org.openmrs.module
@@ -67,10 +68,6 @@
javax.servlet
javax.servlet-api
-
- javax.xml.ws
- jaxws-api
-
org.springframework.ws
spring-ws-core
diff --git a/api/src/main/java/org/openmrs/module/xdssender/XdsSenderConstants.java b/api/src/main/java/org/openmrs/module/xdssender/XdsSenderConstants.java
index 49e8b2d..e7209c0 100644
--- a/api/src/main/java/org/openmrs/module/xdssender/XdsSenderConstants.java
+++ b/api/src/main/java/org/openmrs/module/xdssender/XdsSenderConstants.java
@@ -485,7 +485,17 @@ public final class XdsSenderConstants {
public static final String SCT_TEMPLATE_HISTORY_OF_BLOOD_TRANSFUSIONS = "1.3.6.1.4.1.19376.1.5.3.1.1.9.12";
public static final String LOCATION_SITECODE_ATTRIBUTE_UUID = "6242bf19-207e-4076-9d28-9290525b8ed9";
-
+
+ public static final String SYSTEM_IDENTIFIER_TYPE_NAME = "SYSTEM";
+
+ public static final String PROP_PID_LOCAL = "fhir2.uriPrefix";
+
+ public static final String IDENTIFIER_SYSTEM = "http://openclientregistry.org/fhir/sourceid";
+
+ public static final String SYSTEM_IDENTIFIER_TYPE_UUID = "99F5A4C3-CEEA-4F5F-ABE6-399CD4C9FE24";
+
+ public static final String ECID_IDENTIFIER_TYPE_NAME = "ECID";
+
private XdsSenderConstants() {
}
}
diff --git a/api/src/main/java/org/openmrs/module/xdssender/api/cda/CdaDataUtil.java b/api/src/main/java/org/openmrs/module/xdssender/api/cda/CdaDataUtil.java
index b27b4d2..1d150b3 100644
--- a/api/src/main/java/org/openmrs/module/xdssender/api/cda/CdaDataUtil.java
+++ b/api/src/main/java/org/openmrs/module/xdssender/api/cda/CdaDataUtil.java
@@ -67,6 +67,7 @@
import org.openmrs.api.context.Context;
import org.openmrs.module.xdssender.XdsSenderConfig;
import org.openmrs.module.xdssender.XdsSenderConstants;
+import org.openmrs.module.xdssender.api.xds.XdsUtil;
import org.openmrs.util.OpenmrsConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -88,7 +89,7 @@
*/
@Component("xdssender.CdaDataUtil")
public class CdaDataUtil {
-
+
// NOK codes
private static final List nextOfKinRelations = Arrays.asList("MTH", "FTH", "GRMTH", "GRFTH", "SIB", "CHILD",
"AUNT", "UNCLE", "PGRMTH", "MGRMTH", "PGRFTH", "MGRFTH", "SON", "DAU", "BRO", "SIS", "DOMPART", "FAMMEMB");
@@ -464,11 +465,29 @@ public RecordTarget createRecordTarget(Patient patient) {
// Identifiers
patientRole.setId(new SET());
for (PatientIdentifier pid : patient.getActiveIdentifiers()) {
- II ii = new II(pid.getIdentifierType().getName(), pid.getIdentifier());
- if (!patientRole.getId().contains(ii))
- patientRole.getId().add(ii);
+ // To cater for old records assigned ECID by OpenEMPI, we will Skip adding the ECID identifier type
+ // if it already exists
+ if (!pid.getIdentifierType().getName().equals(XdsSenderConstants.ECID_IDENTIFIER_TYPE_NAME) ) {
+ II ii = new II(pid.getIdentifierType().getName(), pid.getIdentifier());
+ if (!patientRole.getId().contains(ii))
+ patientRole.getId().add(ii);
+ }
}
-
+
+ // Add system identifier
+ II ii = null;
+ II iii = null;
+ try {
+ ii = new II(XdsSenderConstants.SYSTEM_IDENTIFIER_TYPE_NAME, XdsUtil.getPlaceholderSystemIdentifier(patient).getIdentifier());
+ patientRole.getId().add(ii);
+ // Adding an ECID to allow for processing by xds-b-repository in the SHR
+ iii = new II(XdsSenderConstants.ECID_IDENTIFIER_TYPE_NAME, XdsUtil.getPlaceholderSystemIdentifier(patient).getIdentifier());
+ patientRole.getId().add(iii);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+
// Address?
patientRole.setAddr(createAddressSet(patient));
@@ -476,10 +495,14 @@ public RecordTarget createRecordTarget(Patient patient) {
patientRole.setTelecom(createTelecomSet(patient));
// Marital status?
- PersonAttribute civilStatusCode = patient.getAttribute(XdsSenderConstants.ATTRIBUTE_NAME_CIVIL_STATUS);
- if (civilStatusCode != null)
- hl7Patient.setMaritalStatusCode(metadataUtil.getStandardizedCode((Concept) civilStatusCode.getHydratedObject(),
- XdsSenderConstants.CODE_SYSTEM_MARITAL_STATUS, CE.class));
+ try {
+ PersonAttribute civilStatusCode = patient.getAttribute(XdsSenderConstants.ATTRIBUTE_NAME_CIVIL_STATUS);
+ if (civilStatusCode != null)
+ hl7Patient.setMaritalStatusCode(metadataUtil.getStandardizedCode((Concept) civilStatusCode.getHydratedObject(),
+ XdsSenderConstants.CODE_SYSTEM_MARITAL_STATUS, CE.class));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
// Names
hl7Patient.setName(createNameSet(patient));
diff --git a/api/src/main/java/org/openmrs/module/xdssender/api/cda/ClinicalDocumentBuilder.java b/api/src/main/java/org/openmrs/module/xdssender/api/cda/ClinicalDocumentBuilder.java
index 1763db1..df763de 100644
--- a/api/src/main/java/org/openmrs/module/xdssender/api/cda/ClinicalDocumentBuilder.java
+++ b/api/src/main/java/org/openmrs/module/xdssender/api/cda/ClinicalDocumentBuilder.java
@@ -68,11 +68,14 @@ public DocumentModel buildDocument(Patient patient, Encounter encounter) throws
//relevantObs = Context.getObsService().getObservationsByPerson(builder.getRecordTarget());
for (Obs obs : relevantObs) {
- //we want to have all obs groups at the end of the list
- if (obs.hasGroupMembers()) {
- medicationObs.add(obs);
- } else {
- medicationObs.add(0, obs); //this probably is some group member
+ // Ensure that only obs relating to Tests are eliminated from the list
+ if (!obs.getConcept().getConceptClass().getName().equals("Test")) {
+ //we want to have all obs groups at the end of the list
+ if (obs.hasGroupMembers()) {
+ medicationObs.add(obs);
+ } else {
+ medicationObs.add(0, obs); //this probably is some group member
+ }
}
}
diff --git a/api/src/main/java/org/openmrs/module/xdssender/api/cda/EncounterEventListener.java b/api/src/main/java/org/openmrs/module/xdssender/api/cda/EncounterEventListener.java
index c1509b2..f6d564e 100644
--- a/api/src/main/java/org/openmrs/module/xdssender/api/cda/EncounterEventListener.java
+++ b/api/src/main/java/org/openmrs/module/xdssender/api/cda/EncounterEventListener.java
@@ -103,8 +103,9 @@ private void exportEncounter(String encounterUuid) {
LOGGER.warn("Skipped sending Encounter %s (formId is NULL " + "-> probably it's the creating encounter)");
} else {
Patient patient = Context.getPatientService().getPatient(encounter.getPatient().getPatientId());
-
- ecidUpdater.fetchEcidIfRequired(patient);
+
+ // TODO: Replace this with a method that queries OpenCR and fetches/updates the patient data
+ // ecidUpdater.fetchEcidIfRequired(patient);
XdsExportService service = Context.getService(XdsExportService.class);
diff --git a/api/src/main/java/org/openmrs/module/xdssender/api/fhir/FhirResourceDocumentBuilderImpl.java b/api/src/main/java/org/openmrs/module/xdssender/api/fhir/FhirResourceDocumentBuilderImpl.java
index b106cd6..e9895ac 100644
--- a/api/src/main/java/org/openmrs/module/xdssender/api/fhir/FhirResourceDocumentBuilderImpl.java
+++ b/api/src/main/java/org/openmrs/module/xdssender/api/fhir/FhirResourceDocumentBuilderImpl.java
@@ -4,6 +4,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Resource;
import org.marc.everest.datatypes.NullFlavor;
import org.marc.everest.datatypes.TS;
@@ -14,10 +15,12 @@
import org.openmrs.api.impl.BaseOpenmrsService;
import org.openmrs.module.fhir2.api.translators.PatientTranslator;
import org.openmrs.module.fhir2.api.translators.impl.PatientTranslatorImpl;
+import org.openmrs.module.xdssender.XdsSenderConfig;
import org.openmrs.module.xdssender.XdsSenderConstants;
import org.openmrs.module.xdssender.api.cda.CdaDataUtil;
import org.openmrs.module.xdssender.api.cda.model.DocumentModel;
import org.openmrs.module.xdssender.api.fhir.exceptions.ResourceGenerationException;
+import org.openmrs.module.xdssender.api.xds.XdsUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
@@ -82,13 +85,10 @@ public Resource generateFhirResource(Object openmrsEntity) throws ResourceGenera
if (openmrsEntity instanceof Patient) {
Patient patient = (Patient)openmrsEntity;
resource = patientTranslator.toFhirResource(patient);
- localPatientId = Context.getAdministrationService().getGlobalProperty(PROP_PID_LOCAL);
- if (localPatientId == null) {
- throw new ResourceGenerationException("Unable to retrieve the Local PID, ensure that the MPI client module is installed and the \"PID LOCAL\" global property has been set");
- }
- org.hl7.fhir.r4.model.Patient patientResource = (org.hl7.fhir.r4.model.Patient) resource;
- patientResource.addIdentifier().setSystem(IDENTIFIER_SYSTEM).setValue(localPatientId + patient.getUuid());
- resource = patientResource;
+ org.hl7.fhir.r4.model.Patient patientResource;
+ patientResource = checkAndSetSystemIdentifier(patient, (org.hl7.fhir.r4.model.Patient) resource);
+
+ resource = patientResource;
} else {
log.error(String.format("Entity %s not yet implemented", openmrsEntity.getClass().getName()));
throw new ResourceGenerationException("Entity not implemented");
@@ -97,7 +97,35 @@ public Resource generateFhirResource(Object openmrsEntity) throws ResourceGenera
return resource;
}
- /**
+ private org.hl7.fhir.r4.model.Patient checkAndSetSystemIdentifier(Patient patient, org.hl7.fhir.r4.model.Patient patientResource)
+ throws ResourceGenerationException {
+ Boolean isSystemIdentifierDefined = false;
+ for (Identifier identifer: patientResource.getIdentifier()) {
+ if(identifer.getSystem() != null) {
+ if (identifer.getSystem().equals(XdsSenderConstants.IDENTIFIER_SYSTEM)) {
+ isSystemIdentifierDefined = true;
+ break;
+ }
+ }
+ }
+
+ if (!isSystemIdentifierDefined) {
+ PatientIdentifier systemPatientIdentifier = null;
+ try {
+ systemPatientIdentifier = XdsUtil.getPlaceholderSystemIdentifier(patient);
+ }
+ catch (Exception e) {
+ throw new ResourceGenerationException("Unable to retrieve the Local PID, ensure that the \"PID LOCAL\" global property has been set");
+ }
+
+ patientResource.addIdentifier().setSystem(XdsSenderConfig.getInstance().getEcidRoot()).setValue(systemPatientIdentifier.getIdentifier());
+ // qpatientResource.addIdentifier().setSystem(XdsSenderConstants.IDENTIFIER_SYSTEM).setValue(systemPatientIdentifier.getIdentifier());
+ }
+
+ return patientResource;
+ }
+
+ /**
* @should return valid document
*/
@Override
diff --git a/api/src/main/java/org/openmrs/module/xdssender/api/notificationspullpoint/impl/NotificationsPullPointClientImpl.java b/api/src/main/java/org/openmrs/module/xdssender/api/notificationspullpoint/impl/NotificationsPullPointClientImpl.java
index a219b89..a9202db 100644
--- a/api/src/main/java/org/openmrs/module/xdssender/api/notificationspullpoint/impl/NotificationsPullPointClientImpl.java
+++ b/api/src/main/java/org/openmrs/module/xdssender/api/notificationspullpoint/impl/NotificationsPullPointClientImpl.java
@@ -50,118 +50,130 @@
@Component("xdssender.NotificationsPullPointClientImpl")
public class NotificationsPullPointClientImpl extends WebServiceGatewaySupport implements NotificationsPullPointClient {
-
+
// TODO: Move this parameter to the Global Properties section and allow for multiple location tags
private static final String LOCATION_TAG_NAME = "Login Location";
-
+
private static final Logger log = LoggerFactory.getLogger(NotificationsPullPointClientImpl.class);
-
+
+ public static final String FACILITY_QNAME = "facility";
private BigInteger MAX_MESSAGES_PER_REQUEST = BigInteger.valueOf(100);
-
+
@Autowired
private XdsSenderConfig config;
-
+
@Override
public List getNewMessages() {
LocationTag loginLocationTag = Context.getLocationService().getLocationTagByName(LOCATION_TAG_NAME);
List locations = Context.getLocationService().getLocationsByTag(loginLocationTag);
List returnMessages = new ArrayList();
-
+
for (Location location : locations) {
returnMessages.addAll(this.getNewMessages(location));
}
-
+
if (returnMessages.size() > 0) {
return returnMessages;
}
-
+
return null;
}
-
+
@Override
public List getNewMessages(Location currentLocation) {
GetMessages request = new GetMessages();
String siteCode = null;
-
+
request.setMaximumNumber(MAX_MESSAGES_PER_REQUEST);
-
+
for (LocationAttribute attribute : currentLocation.getAttributes()) {
if (attribute.getAttributeType().getUuid().equals(XdsSenderConstants.LOCATION_SITECODE_ATTRIBUTE_UUID)) {
siteCode = attribute.getValue().toString();
}
}
-
+
log.debug("Location SiteCode, Name: ID: SiteCode {}",
currentLocation.getName() + ": " + currentLocation.getId() + ": " + siteCode);
- request.getOtherAttributes().put(new QName("facility"), siteCode);
-
+ request.getOtherAttributes().put(new QName(FACILITY_QNAME), siteCode);
+
+ List result = new ArrayList<>();
GetMessagesResponse response;
try {
// response = (GetMessagesResponse) getResponse(request);
response = (GetMessagesResponse) getResponseHttpClient(request);
- List result = new ArrayList<>();
-
HL7Service hl7Service = Context.getHL7Service();
for (NotificationMessageHolderType notification : response.getNotificationMessage()) {
- // TODO: Ensure that this casting is working properly
Element el = (Element) notification.getMessage().getAny();
- // Message e = new PipeParser().parse(el.getTextContent());
+ String decodedMessage = new String(Base64.decodeBase64(el.getTextContent()), "UTF-8");
String parsedMessage = OruR01Util
- .changeMessageVersionFrom251To25(el.getTextContent().replace("\n", Character.toString((char) 13)) // Replace new line character with it's ASCII equivalent
+ .changeMessageVersionFrom251To25(decodedMessage.replace("\n", Character.toString((char) 13)) // Replace new line character with it's ASCII equivalent
.replaceAll("\\[[0-9]{4}\\]", "")); // Remove the time component from the birthdate to fix a HL7 parsing error
-
+
log.debug(parsedMessage);
Message message = hl7Service.parseHL7String(parsedMessage);
result.add(message);
}
-
- return result;
-
}
catch (Exception e) {
log.debug("Error getting response in NotificationsPullPointClientImpl: ", e);
e.printStackTrace();
+ } finally {
+ return result;
}
-
- return null;
-
}
-
+
private Object getResponse(Object requestPayload) throws Exception {
-
+
WebServiceMessageCallback addAuthorizationHeader = new WebServiceMessageCallback() {
-
+
@Override
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
addAuthorizationHeader(requestPayload);
}
};
-
+
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
-
+
marshaller.setContextPath("org.openmrs.module.xdssender.notificationspullpoint");
marshaller.afterPropertiesSet();
-
+
WebServiceTemplate webServiceTemplate = getWebServiceTemplate();
webServiceTemplate.setMarshaller(marshaller);
return webServiceTemplate.marshalSendAndReceive(config.getNotificationsPullPointEndpoint(), requestPayload,
addAuthorizationHeader);
}
-
+
private Object getResponseHttpClient(GetMessages requestPayload) throws Exception {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("org.openmrs.module.xdssender.notificationspullpoint");
marshaller.afterPropertiesSet();
StringResult result = new StringResult();
marshaller.marshal(requestPayload, result);
-
+
OkHttpClient client = new OkHttpClient().newBuilder().build();
MediaType mediaType = MediaType.parse("text/xml; charset=utf-8");
+ String facilitySiteCode = requestPayload.getOtherAttributes().get(new QName(FACILITY_QNAME));
+ String getMessagesPayload = String.format(""
+ + "\r\n"
+ + " \r\n"
+ + " \r\n"
+ + " \r\n"
+ + " 100\r\n"
+ + " \r\n"
+ + " \r\n"
+ + "",
+ facilitySiteCode);
RequestBody body = RequestBody.create(
- "\r\n \r\n \r\n \r\n 100\r\n \r\n \r\n",
+ getMessagesPayload,
mediaType);
- // RequestBody body = RequestBody.create(result.toString(), mediaType);
Request request = new Request.Builder().url(config.getNotificationsPullPointEndpoint()).method("POST", body)
.addHeader("Content-Type", "text/xml; charset=utf-8")
.addHeader("Accept", "text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
@@ -169,14 +181,14 @@ private Object getResponseHttpClient(GetMessages requestPayload) throws Exceptio
config.getNotificationsPullPointPassword()))
.build();
Response response = client.newCall(request).execute();
-
+
JAXBContext jaxbContext = JAXBContext.newInstance("org.openmrs.module.xdssender.notificationspullpoint");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
String responseText = response.body().string();
Object res = unmarshaller.unmarshal(IOUtils.toInputStream(responseText));
-
+
return res;
-
+
}
private void addAuthorizationHeader() {
@@ -185,7 +197,7 @@ private void addAuthorizationHeader() {
connection.getConnection().addRequestProperty("Authorization", generateBasicAuthenticationHeader(
config.getNotificationsPullPointUsername(), config.getNotificationsPullPointPassword()));
}
-
+
private void addAuthorizationHeader(Object requestPayload) {
log.debug("Setting authorization headers");
TransportContext context = TransportContextHolder.getTransportContext();
@@ -199,10 +211,10 @@ private void addAuthorizationHeader(Object requestPayload) {
log.debug(conn.getRequestProperty("Content-Length"));
}
}
-
+
private static String generateBasicAuthenticationHeader(String userName, String userPassword) {
byte[] bytesEncoded = Base64.encodeBase64((userName + ":" + userPassword).getBytes(Charset.forName("UTF-8")));
return "Basic " + new String(bytesEncoded, Charset.forName("UTF-8"));
}
-
+
}
diff --git a/api/src/main/java/org/openmrs/module/xdssender/api/service/impl/XdsExportServiceImpl.java b/api/src/main/java/org/openmrs/module/xdssender/api/service/impl/XdsExportServiceImpl.java
index aa02897..a350331 100644
--- a/api/src/main/java/org/openmrs/module/xdssender/api/service/impl/XdsExportServiceImpl.java
+++ b/api/src/main/java/org/openmrs/module/xdssender/api/service/impl/XdsExportServiceImpl.java
@@ -2,25 +2,32 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dcm4chee.xds2.infoset.ihe.ProvideAndRegisterDocumentSetRequestType;
import org.dcm4chee.xds2.infoset.ihe.ProvideAndRegisterDocumentSetRequestType.Document;
+import org.dcm4chee.xds2.infoset.rim.IdentifiableType;
import org.dcm4chee.xds2.infoset.rim.RegistryResponseType;
import org.openmrs.Encounter;
import org.openmrs.Patient;
+import org.openmrs.PatientIdentifier;
+import org.openmrs.PatientIdentifierType;
+import org.openmrs.api.context.Context;
import org.openmrs.api.impl.BaseOpenmrsService;
import org.openmrs.module.xdssender.XdsSenderConfig;
import org.openmrs.module.xdssender.api.cda.ClinicalDocumentBuilder;
import org.openmrs.module.xdssender.api.cda.model.DocumentModel;
import org.openmrs.module.xdssender.api.fhir.FhirResourceDocumentBuilder;
+import org.openmrs.module.xdssender.api.fhir.exceptions.ResourceGenerationException;
import org.openmrs.module.xdssender.api.hl7.ORM_O01DocumentBuilder;
import org.openmrs.module.xdssender.api.model.DocumentData;
import org.openmrs.module.xdssender.api.model.DocumentInfo;
import org.openmrs.module.xdssender.api.service.XdsExportService;
import org.openmrs.module.xdssender.api.xds.MessageUtil;
import org.openmrs.module.xdssender.api.xds.XdsSender;
+import org.openmrs.module.xdssender.api.xds.XdsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -50,6 +57,7 @@ public class XdsExportServiceImpl extends BaseOpenmrsService implements XdsExpor
@Override
public DocumentInfo exportProvideAndRegister(Encounter encounter, Patient patient) {
try {
+
DocumentModel clinicalDocModel = clinicalDocBuilder.buildDocument(patient, encounter);
DocumentInfo clinicalDocInfo = new DocumentInfo(encounter, patient, clinicalDocModel,
"text/xsl", config.getProviderRoot());
@@ -66,21 +74,23 @@ public DocumentInfo exportProvideAndRegister(Encounter encounter, Patient patien
additionalData.add(labOrderDoc);
}
+ // Assign a placeholder System Identifier to be used for validating against the MPI
+ // patient.addIdentifier(XdsUtil.getPlaceholderSystemIdentifier(patient));
DocumentData patientFhirResourceDoc = null;
DocumentModel patientFhirResourceDocModel = fhirResourceBuilder.buildDocument(patient, encounter);
if (patientFhirResourceDocModel != null) {
DocumentInfo patientFhirResourceDocInfo = new DocumentInfo(encounter, patient, patientFhirResourceDocModel,
- "text/plain", config.getProviderRoot());
+ "text/fhir", config.getProviderRoot());
patientFhirResourceDoc = new DocumentData(patientFhirResourceDocInfo, patientFhirResourceDocModel.getData());
additionalData.add(patientFhirResourceDoc);
- }
+ }
ProvideAndRegisterDocumentSetRequestType request = messageUtil.createProvideAndRegisterDocument(clinicalDoc,
additionalData, encounter);
logRequest(request);
-
+
RegistryResponseType response = xdsSender.sendProvideAndRegister(request);
if (!response.getStatus().contains("Success"))
diff --git a/api/src/main/java/org/openmrs/module/xdssender/api/xds/MessageUtil.java b/api/src/main/java/org/openmrs/module/xdssender/api/xds/MessageUtil.java
index fd5d64e..9f605b8 100644
--- a/api/src/main/java/org/openmrs/module/xdssender/api/xds/MessageUtil.java
+++ b/api/src/main/java/org/openmrs/module/xdssender/api/xds/MessageUtil.java
@@ -41,7 +41,7 @@
@Component("xdssender.MessageUtil")
public class MessageUtil {
- private static final String ECID_NAME = "ECID";
+ private static final String ECID_NAME = "SYSTEM";
private static final String CODE_NATIONAL_NAME = "Code National";
@@ -64,6 +64,10 @@ public class MessageUtil {
@Autowired
private XdsSenderConfig config;
+ private String identifierAssigningAuthority;
+
+ private String identifierAssigningAuthorityId;
+
public ProvideAndRegisterDocumentSetRequestType createProvideAndRegisterDocument(DocumentData clinicalData,
DocumentData msgData,
Encounter encounter)
@@ -96,7 +100,7 @@ public ProvideAndRegisterDocumentSetRequestType createProvideAndRegisterDocument
// createProvideAndRegisterClinicalDocument can be replaced by methods used to generate the ORM_O01 message
ProvideAndRegisterDocumentSetRequestType result = createProvideAndRegisterClinicalDocument(
clinicalData.getDocumentContent(), clinicalData.getDocumentInfo(), encounter);
-
+
if (additionalData != null && additionalData.size() > 0) {
Integer setid = 2;
@@ -123,7 +127,15 @@ public ProvideAndRegisterDocumentSetRequestType createProvideAndRegisterClinical
final DocumentInfo info,
Encounter encounter)
throws JAXBException {
- String patientId = getPatientIdentifier(info).getIdentifier();
+ String patientId = null;
+ try {
+ patientId = XdsUtil.getPlaceholderSystemIdentifier(info.getPatient()).getIdentifier();
+ }
+ catch (Exception e) {
+ patientId = getPatientIdentifier(info).getIdentifier();
+ e.printStackTrace();
+ }
+
String location = getPatientLocation(info).getName();
ProvideAndRegisterDocumentSetRequestType retVal = new ProvideAndRegisterDocumentSetRequestType();
@@ -195,13 +207,17 @@ public ProvideAndRegisterDocumentSetRequestType createProvideAndRegisterClinical
.toString());
InfosetUtil.addOrOverwriteSlot(oddRegistryObject, XDSConstants.SLOT_NAME_CREATION_TIME, new SimpleDateFormat(
"yyyyMMddHHmmss").format(new Date()));
-
+
+ identifierAssigningAuthority = XdsSenderConstants.IDENTIFIER_SYSTEM;
+
+ identifierAssigningAuthorityId = Context.getAdministrationService().getGlobalProperty(XdsSenderConstants.PROP_PID_LOCAL, "http://openmrs.org");
+
// Unique identifier
xdsUtil.addExtenalIdentifier(oddRegistryObject, XDSConstants.UUID_XDSDocumentEntry_uniqueId,
String.format("2.25.%s", UUID.randomUUID().getLeastSignificantBits()).replaceAll("-", ""),
"XDSDocumentEntry.uniqueId");
xdsUtil.addExtenalIdentifier(oddRegistryObject, XDSConstants.UUID_XDSDocumentEntry_patientId,
- String.format("%s^^^%s&%s&NI", patientId, config.getEcidRoot(), config.getEcidRoot()),
+ String.format("%s^^^%s&%s&%s&NI", patientId, identifierAssigningAuthority, identifierAssigningAuthorityId, config.getEcidRoot()),
"XDSDocumentEntry.patientId");
// Set classifications
@@ -228,7 +244,11 @@ public ProvideAndRegisterDocumentSetRequestType createProvideAndRegisterClinical
InfosetUtil.addOrOverwriteSlot(regPackage, XDSConstants.SLOT_NAME_SUBMISSION_TIME, now.getValue());
xdsUtil.addCodedValueClassification(regPackage, XDSConstants.UUID_XDSSubmissionSet_contentTypeCode,
info.getClassCode(), "LOINC", "XDSSubmissionSet.contentTypeCode");
-
+
+ identifierAssigningAuthority = XdsSenderConstants.IDENTIFIER_SYSTEM;
+
+ identifierAssigningAuthorityId = Context.getAdministrationService().getGlobalProperty(XdsSenderConstants.PROP_PID_LOCAL, "http://openmrs.org");
+
// Submission set external identifiers
xdsUtil.addExtenalIdentifier(regPackage, XDSConstants.UUID_XDSSubmissionSet_uniqueId,
String.format("2.25.%s", UUID.randomUUID().getLeastSignificantBits()).replaceAll("-", ""),
@@ -237,7 +257,8 @@ public ProvideAndRegisterDocumentSetRequestType createProvideAndRegisterClinical
String.format("2.25.%s", UUID.randomUUID().getLeastSignificantBits()).replaceAll("-", ""),
"XDSSubmissionSet.sourceId");
xdsUtil.addExtenalIdentifier(regPackage, XDSConstants.UUID_XDSSubmissionSet_patientId,
- String.format("%s^^^%s&%s&NI", patientId, config.getEcidRoot(), config.getEcidRoot()),
+ String.format("%s^^^%s&%s&%s&NI", patientId, identifierAssigningAuthority, identifierAssigningAuthorityId, config.getEcidRoot()),
+ // String.format("%s^^^%s&%s&NI", patientId, config.getEcidRoot(), config.getEcidRoot()),
"XDSSubmissionSet.patientId");
// Add the eo to the submission
@@ -333,7 +354,7 @@ public PatientIdentifier getPatientIdentifier(DocumentInfo info) {
PatientIdentifier result = info.getPatient().getPatientIdentifier();
for (PatientIdentifier pid : info.getPatient().getIdentifiers()) {
- if (pid.getIdentifierType().getName().equals(ECID_NAME)) {
+ if (pid.getIdentifierType().getName().equals(XdsSenderConstants.SYSTEM_IDENTIFIER_TYPE_NAME)) {
result = pid;
}
}
@@ -350,7 +371,7 @@ public PatientIdentifier getNationalPatientIdentifier(DocumentInfo info) {
}
return result;
}
-
+
public PatientIdentifier getSitePatientIdentifier(DocumentInfo info) {
PatientIdentifier result = info.getPatient().getPatientIdentifier();
@@ -396,7 +417,14 @@ private SubmitObjectsRequest addAssociation(SubmitObjectsRequest registryRequest
}
private ExtrinsicObjectType createExtrinsicObjectType(DocumentInfo info, Encounter encounter) throws JAXBException {
- String patientId = getPatientIdentifier(info).getIdentifier();
+ String patientId = null;
+ try {
+ patientId = XdsUtil.getPlaceholderSystemIdentifier(info.getPatient()).getIdentifier();
+ }
+ catch (Exception e) {
+ patientId = getPatientIdentifier(info).getIdentifier();
+ e.printStackTrace();
+ }
String location = getPatientLocation(info).getName();
ExtrinsicObject extrinsicObject = new ExtrinsicObject(patientId, location);
@@ -437,11 +465,17 @@ private ExtrinsicObjectType createExtrinsicObjectType(DocumentInfo info, Encount
}
private void addUniqueIdentifier(ExtrinsicObjectType extrinsicObject, String patientId) throws JAXBException {
+ identifierAssigningAuthority = XdsSenderConstants.IDENTIFIER_SYSTEM;
+
+ identifierAssigningAuthorityId = Context.getAdministrationService().getGlobalProperty(XdsSenderConstants.PROP_PID_LOCAL, "http://openmrs.org");
+
xdsUtil.addExtenalIdentifier(extrinsicObject, XDSConstants.UUID_XDSDocumentEntry_uniqueId,
String.format("2.25.%s", UUID.randomUUID().getLeastSignificantBits()).replaceAll("-", ""),
"XDSDocumentEntry.uniqueId");
xdsUtil.addExtenalIdentifier(extrinsicObject, XDSConstants.UUID_XDSDocumentEntry_patientId,
- String.format("%s^^^%s&%s&NI", patientId, config.getEcidRoot(), config.getEcidRoot()),
+ String.format("%s^^^%s&%s&%s&NI", patientId, identifierAssigningAuthority, identifierAssigningAuthorityId, config.getEcidRoot()),
+ // String.format("%s^^^%s&%s&NI", patientId, config.getEcidRoot(), config.getEcidRoot()),
+ // String.format("%s", patientId),
"XDSDocumentEntry.patientId");
}
diff --git a/api/src/main/java/org/openmrs/module/xdssender/api/xds/XdsUtil.java b/api/src/main/java/org/openmrs/module/xdssender/api/xds/XdsUtil.java
index 5873fd5..d9c0bfb 100644
--- a/api/src/main/java/org/openmrs/module/xdssender/api/xds/XdsUtil.java
+++ b/api/src/main/java/org/openmrs/module/xdssender/api/xds/XdsUtil.java
@@ -1,6 +1,7 @@
package org.openmrs.module.xdssender.api.xds;
import groovy.text.GStringTemplateEngine;
+import org.dcm4chee.xds2.common.XDSConstants;
import org.dcm4chee.xds2.infoset.rim.ClassificationType;
import org.dcm4chee.xds2.infoset.rim.ExternalIdentifierType;
import org.dcm4chee.xds2.infoset.rim.InternationalStringType;
@@ -11,7 +12,11 @@
import org.hl7.fhir.r4.model.*;
import org.openmrs.Patient;
import org.openmrs.PatientIdentifier;
+import org.openmrs.PatientIdentifierType;
+import org.openmrs.api.context.Context;
import org.openmrs.module.xdssender.XdsSenderConfig;
+import org.openmrs.module.xdssender.XdsSenderConstants;
+import org.openmrs.module.xdssender.api.fhir.exceptions.ResourceGenerationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,6 +39,23 @@ public final class XdsUtil {
private static final Logger logger = LoggerFactory.getLogger(XdsUtil.class);
+ public static PatientIdentifier getPlaceholderSystemIdentifier(Patient patient) throws Exception {
+ PatientIdentifierType systemIdentifierType = new PatientIdentifierType();
+ systemIdentifierType.setName(XdsSenderConstants.SYSTEM_IDENTIFIER_TYPE_NAME);
+ systemIdentifierType.setUuid(XdsSenderConstants.SYSTEM_IDENTIFIER_TYPE_UUID);
+
+ PatientIdentifier systemIdentifier = new PatientIdentifier();
+ systemIdentifier.setIdentifierType(systemIdentifierType);
+ String localPatientId = Context.getAdministrationService().getGlobalProperty(XdsSenderConstants.PROP_PID_LOCAL, "http://openmrs.org");
+ if (localPatientId == null) {
+ throw new Exception("Unable to retrieve the Local PID, ensure that the MPI client module is installed and the \"PID LOCAL\" global property has been set");
+ }
+ // systemIdentifier.setIdentifier(localPatientId + "/" + patient.getUuid());
+ systemIdentifier.setIdentifier(patient.getUuid());
+
+ return systemIdentifier;
+ }
+
public String parseCcdToHtml(Bundle resource, File ccdTemplate) throws IOException, ClassNotFoundException {
// TODO Find a better way to filter the obs of interest
List codes = new ArrayList() {{
diff --git a/api/src/test/java/org/openmrs/module/xdssender/api/service/impl/XdsExportServiceImplTest.java b/api/src/test/java/org/openmrs/module/xdssender/api/service/impl/XdsExportServiceImplTest.java
new file mode 100644
index 0000000..0fc002a
--- /dev/null
+++ b/api/src/test/java/org/openmrs/module/xdssender/api/service/impl/XdsExportServiceImplTest.java
@@ -0,0 +1,40 @@
+package org.openmrs.module.xdssender.api.service.impl;
+
+import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Test;
+import org.openmrs.Encounter;
+import org.openmrs.Patient;
+import org.openmrs.Visit;
+import org.openmrs.api.context.Context;
+import org.openmrs.module.xdssender.api.cda.model.DocumentModel;
+import org.openmrs.module.xdssender.api.fhir.FhirResourceDocumentBuilder;
+import org.openmrs.module.xdssender.api.model.DocumentInfo;
+import org.openmrs.module.xdssender.api.service.XdsExportService;
+import org.openmrs.test.BaseModuleContextSensitiveTest;
+import org.springframework.test.context.ContextConfiguration;
+import java.util.List;
+
+import static org.junit.Assert.assertNotNull;
+
+@ContextConfiguration(locations = { "classpath*:moduleApplicationContext.xml", "classpath*:applicationContext-service.xml" }, inheritLocations = false)
+public class XdsExportServiceImplTest extends BaseModuleContextSensitiveTest {
+
+ private static final String DATASET = "lab-dataset.xml";
+ private static final String GLOBAL_CONFIGS = "global-configs.xml";
+
+ @Before
+ public void setUp() throws Exception {
+ executeDataSet(DATASET);
+ executeDataSet(GLOBAL_CONFIGS);
+ }
+
+ @Test
+ public void testExportProvideAndRegister() {
+ Patient patient = Context.getPatientService().getPatient(10);
+ Encounter encounter = Context.getEncounterService().getEncounter(21);
+ XdsExportService xdsExportService = Context.getService(XdsExportService.class);
+ DocumentInfo di = xdsExportService.exportProvideAndRegister(encounter, patient);
+ assertNotNull(di);
+ }
+}
diff --git a/api/src/test/resources/global-configs.xml b/api/src/test/resources/global-configs.xml
index d5327e2..bbc844b 100644
--- a/api/src/test/resources/global-configs.xml
+++ b/api/src/test/resources/global-configs.xml
@@ -1,8 +1,21 @@
+
+
+
+
+ uuid="FAB088A2-7A9E-404A-A487-06258B65FF5C"/>
diff --git a/api/src/test/resources/lab-dataset.xml b/api/src/test/resources/lab-dataset.xml
index 0cd0d5f..294c0f8 100644
--- a/api/src/test/resources/lab-dataset.xml
+++ b/api/src/test/resources/lab-dataset.xml
@@ -47,6 +47,10 @@
+
+
+
+
@@ -62,6 +66,11 @@
+
+
+
+
+
@@ -77,18 +86,11 @@
creator="1" date_created="2005-01-06 00:00:00"/>
-
-
-
-
+
+
+
+
+
-
+
+
+
+
+
-
-
+
+
-
-
+ preferred="0" location_id="2"/>
+
+
-
-
-
+
+
+
+
+ creator="1" date_created="2005-01-06 00:00:00" voided="0" form_id="1"/>
+
+
+
+
-
-
-
\ No newline at end of file
+ uuid="549c78dc-31da-11e8-acac-c3add5b19973"
+ form_id="1"
+ location_id="2"
+ visit_id="1"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/api/src/test/resources/xds-dataset.xml b/api/src/test/resources/xds-dataset.xml
index 1b0ff32..3b1312f 100644
--- a/api/src/test/resources/xds-dataset.xml
+++ b/api/src/test/resources/xds-dataset.xml
@@ -3,7 +3,7 @@
-
+
f037e97b-471e-4898-a07c-b8e169e0ddc4
+
+ xdssender.ecidRoot
+ ECID Root
+ http://openclientregistry.org/fhir/sourceid
+
+