Commit d30fb090 authored by R.W.Majeed's avatar R.W.Majeed

extract patient and encounter id during CDA parsing. if encounter patient...

extract patient and encounter id during CDA parsing. if encounter patient merge is detected, delete facts for encounter
parent a1db0fca
......@@ -123,15 +123,17 @@ public abstract class AbstractCDAImporter implements CDAProcessor{
throw new CDAException("Transformation to EAV failed", e);
}
}
protected Anonymizer getAnonymizer() {
return cdaToDataWarehouse.getAnonymizer();
}
@Override
public CDAStatus createOrUpdate(Document document, String documentId, String templateId) throws CDAException{
public CDAStatus createOrUpdate(Document document, String documentId, String templateId, String[] patientId, String[] encounterId) throws CDAException{
// not using provided patientId, encounterId, documentId
// use IDs from EAV transformation result
// transform CDA document to EAV XML in temporary file
Path tempEAV = transform(document, templateId);
CDAStatus status;
try{
// parse EAV XML and insert into fact table
......
......@@ -32,6 +32,8 @@ import de.sekmi.histream.ObservationException;
import de.sekmi.histream.ObservationFactory;
import de.sekmi.histream.i2b2.DataDialect;
import de.sekmi.histream.i2b2.I2b2Inserter;
import de.sekmi.histream.i2b2.I2b2Visit;
import de.sekmi.histream.i2b2.PostgresVisitStore;
/**
* CDA importer pojo EJB. Processed CDA documents are loaded into
......@@ -45,6 +47,7 @@ public class CDAImporter extends AbstractCDAImporter implements AutoCloseable{
private I2b2Inserter inserter;
private ObservationFactory factory;
private ZoneId localZone;
private PostgresVisitStore visitStore;
/**
* Construct a CDAImporter
......@@ -59,6 +62,7 @@ public class CDAImporter extends AbstractCDAImporter implements AutoCloseable{
public CDAImporter(ObservationFactory factory, Preferences prefs, Anonymizer anonymizer) throws NamingException, SQLException, IOException {
super(anonymizer);
this.factory = factory;
this.visitStore = (PostgresVisitStore)factory.getExtension(I2b2Visit.class);
this.localZone = ZoneId.of(prefs.get(PreferenceKey.timeZoneId));
log.info("Default timezone for CDA documents: "+localZone);
InitialContext ctx = new InitialContext();
......@@ -131,17 +135,38 @@ public class CDAImporter extends AbstractCDAImporter implements AutoCloseable{
return inserter;
}
private void encounterPatientMerge(String documentId, String[] patientId, String[] encounterId) {
// extract encounter id, patient id.
// if encounter exists and has different patient assigned, delete all facts for the encounter id. Then allow reassignment of new patient id
String encId = getAnonymizer().calculateEncounterPseudonym(encounterId[0], encounterId[1]);
String patId = getAnonymizer().calculatePatientPseudonym(patientId[0], patientId[1]);
log.info("Using patid="+patId+", encid="+encId+", docid="+documentId);
I2b2Visit visit = visitStore.findVisit(encId);
if( false == patId.equals(visit.getPatientId()) ) {
log.warning("Encounter "+encId+" assigned different patient "+patId);
// delete all facts for the encounter
try {
inserter.purgeVisit(visit.getNum());
} catch (SQLException e) {
log.log(Level.WARNING,"Failed to purge facts for visit "+visit.getNum(), e);
}
// update patient id
visit.setPatientId(patId);
}
}
@Override
public synchronized CDAStatus createOrUpdate(Document document, String documentId, String templateId)
public synchronized CDAStatus createOrUpdate(Document document, String documentId, String templateId, String[] patientId, String[] encounterId)
throws CDAException {
//log.info("Using patid="+patientId+", encid="+encounterId+", docid="+documentId);
encounterPatientMerge(documentId, patientId, encounterId);
final List<ObservationException> insertErrors = new LinkedList<>();
inserter.setErrorHandler(insertErrors::add);
// process document
CDAStatus status = null;
try{
status = super.createOrUpdate(document, documentId, templateId);
status = super.createOrUpdate(document, documentId, templateId, patientId, encounterId);
}finally{
inserter.setErrorHandler(null);
inserter.resetErrorCount();
......
......@@ -16,7 +16,7 @@ public interface CDAProcessor {
* @throws CDAException processing error
* @throws UnsupportedTemplateException template not supported
*/
public CDAStatus createOrUpdate(Document document, String documentId, String templateId) throws CDAException, UnsupportedTemplateException;
public CDAStatus createOrUpdate(Document document, String documentId, String templateId, String[] patientId, String[] encounterId) throws CDAException, UnsupportedTemplateException;
public Path transform(Document cda, String templateId) throws CDAException;
/**
......
......@@ -151,8 +151,10 @@ public class Binary implements ExternalInterface{
if( isValid ){
// check arguments/valid id
// otherwise return HTTP_BAD_REQUEST
String[] patientId = parser.extractPatientId(cda);
String[] encounterId = parser.extractEncounterId(cda);
// process document
CDAStatus stat = processor.createOrUpdate(cda, documentId, templateId);
CDAStatus stat = processor.createOrUpdate(cda, documentId, templateId, patientId, encounterId);
// check whether document was created or updated, return 201 or 200
if( stat.getStatus() == Status.Created ){
// create location conforming to FHIR specification
......
......@@ -119,7 +119,10 @@ public class DocumentRepository implements DocumentRepositoryPortType, ExternalI
//ids = parser.extractIDs(cda);
// TODO compare to IDs from XDS call
// process document (XXX catch errors)
processor.createOrUpdate(cda, documentId, templateId);
String[] patientId = parser.extractPatientId(cda);
String[] encounterId = parser.extractEncounterId(cda);
processor.createOrUpdate(cda, documentId, templateId, patientId, encounterId);
resp.setStatus(XDSConstants.RESPONSE_SUCCESS);
} catch (CDAException e) {
log.log(Level.WARNING, "Unable to import CDA", e);
......@@ -128,6 +131,9 @@ public class DocumentRepository implements DocumentRepositoryPortType, ExternalI
Throwable cause = e.getCause();
if( null == cause )cause = e;
return createErrorResponse(XDSConstants.ERR_REPO_ERROR, "Error during import of CDA. See server log", cause);
} catch (XPathExpressionException e) {
log.log(Level.WARNING, "Unable to extract patient or encounter id", e);
return createErrorResponse(XDSConstants.ERR_REPO_ERROR, "Error during import of CDA. See server log", e);
}
}else{
// failed
......
......@@ -61,7 +61,7 @@ public class HashtableStore implements CDAProcessor{
this.map = new Hashtable<>();
}
@Override
public CDAStatus createOrUpdate(Document document, String documentId, String templateId)
public CDAStatus createOrUpdate(Document document, String documentId, String templateId, String[] patientId, String[] encounterId)
throws CDAException {
VirtualDocument doc = map.get(documentId);
if( doc == null ){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment