...
 
Commits (3)
......@@ -66,6 +66,8 @@ public class CDAImporter extends AbstractCDAImporter implements AutoCloseable{
super(anonymizer);
this.factory = factory;
this.visitStore = (PostgresVisitStore)factory.getExtension(I2b2Visit.class);
// set visit store to reject patient changes, in the case we miss one here (should not happen, TODO remove later)
this.visitStore.setRejectPatientChange(true);
this.patientStore = (PostgresPatientStore)factory.getExtension(I2b2Patient.class);
this.localZone = ZoneId.of(prefs.get(PreferenceKey.timeZoneId));
log.info("Default timezone for CDA documents: "+localZone);
......@@ -139,16 +141,23 @@ public class CDAImporter extends AbstractCDAImporter implements AutoCloseable{
return inserter;
}
private void encounterPatientMerge(String documentId, String[] patientId, String[] encounterId) {
private enum MergeResult{
NewVisit,
ExistingVisitNewPatient,
ExistingVisitDifferentPatient,
ExistingVisitSamePatient
}
private MergeResult 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
MergeResult result;
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( visit == null ) {
log.info("No existing visit found for "+encId);
result = MergeResult.NewVisit;
}else {
log.info("Existing visit found with patid="+visit.getPatientId());
// find new patient
......@@ -158,10 +167,15 @@ public class CDAImporter extends AbstractCDAImporter implements AutoCloseable{
// new patient unknown, delete old encounter data
log.warning("Encounter "+encId+" assigned a new (unknown) patient "+patId);
deleteFacts = true;
result = MergeResult.ExistingVisitNewPatient;
}else if( patient.getNum() != visit.getPatientNum() ) {
// new patient differs from assigned patient
log.warning("Encounter "+encId+" assigned different patient "+patId);
// delete all facts for the encounter
result = MergeResult.ExistingVisitDifferentPatient;
deleteFacts = true;
}else {
result = MergeResult.ExistingVisitSamePatient;
deleteFacts = true;
}
if( deleteFacts ) {
......@@ -173,13 +187,19 @@ public class CDAImporter extends AbstractCDAImporter implements AutoCloseable{
}
// TODO make sure that the new patient is assigned later when it is created
}
return result;
}
@Override
public synchronized CDAStatus createOrUpdate(Document document, String documentId, String templateId, String[] patientId, String[] encounterId)
throws CDAException {
encounterPatientMerge(documentId, patientId, encounterId);
MergeResult merge = encounterPatientMerge(documentId, patientId, encounterId);
if( merge == MergeResult.ExistingVisitNewPatient || merge == MergeResult.ExistingVisitDifferentPatient ) {
log.info("Rejecting change of patient for existing visit");
// for now, reject the update
// TODO make sure that the previous facts are deleted
return CDAStatus.rejected(documentId);
}
final List<ObservationException> insertErrors = new LinkedList<>();
inserter.setErrorHandler(insertErrors::add);
......
......@@ -9,7 +9,8 @@ public class CDAStatus {
public enum Status{
Created,
Updated
Updated,
Rejected
}
public CDAStatus(CDASummary summary, Status status){
......@@ -23,6 +24,9 @@ public class CDAStatus {
public static CDAStatus updated(CDASummary summary){
return new CDAStatus(summary, Status.Updated);
}
public static CDAStatus rejected(String documentId) {
return new CDAStatus(new DocumentIdSummary(documentId), Status.Rejected);
}
public Date getLastModified(){
return summary.getLastModified();
......
package org.aktin.cda;
import java.util.Date;
public class DocumentIdSummary implements CDASummary {
private String documentId;
public DocumentIdSummary(String documentId) {
this.documentId = documentId;
}
@Override
public String getDocumentId() {
return documentId;
}
@Override
public Date getLastModified() {
return null;
}
@Override
public Date getCreated() {
return null;
}
@Override
public String getVersion() {
return null;
}
}
......@@ -169,6 +169,8 @@ public class Binary implements ExternalInterface{
// Location header not allowed for status 200
hallihallo2.addUpdated();
importSuccessful = true;
}else if( stat.getStatus() == Status.Rejected ) {
response = Response.status(409); // HTTP conflict
}else{
throw new UnsupportedOperationException("Unexpected CDA status "+stat.getStatus());
}
......