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

fixed updating visit for patient change

parent 638dcebf
...@@ -47,7 +47,7 @@ public class SimpleVisitExtension implements Extension<VisitImpl>{ ...@@ -47,7 +47,7 @@ public class SimpleVisitExtension implements Extension<VisitImpl>{
} }
VisitImpl visit = new VisitImpl(); VisitImpl visit = new VisitImpl();
visit.setId((String)args[0]); visit.setId((String)args[0]);
visit.setPatientId(((Patient)args[1]).getId()); visit.setPatient(((Patient)args[1]));
ExternalSourceType source = (ExternalSourceType)args[2]; ExternalSourceType source = (ExternalSourceType)args[2];
visit.setSourceId(source.getSourceId()); visit.setSourceId(source.getSourceId());
visit.setSourceTimestamp(source.getSourceTimestamp()); visit.setSourceTimestamp(source.getSourceTimestamp());
......
package de.sekmi.histream.impl; package de.sekmi.histream.impl;
import java.util.Objects;
/* /*
* #%L * #%L
* histream * histream
...@@ -24,6 +26,7 @@ package de.sekmi.histream.impl; ...@@ -24,6 +26,7 @@ package de.sekmi.histream.impl;
import de.sekmi.histream.DateTimeAccuracy; import de.sekmi.histream.DateTimeAccuracy;
import de.sekmi.histream.ext.Patient;
import de.sekmi.histream.ext.StoredExtensionType; import de.sekmi.histream.ext.StoredExtensionType;
import de.sekmi.histream.ext.Visit; import de.sekmi.histream.ext.Visit;
...@@ -49,9 +52,10 @@ public class VisitImpl extends StoredExtensionType implements Visit { ...@@ -49,9 +52,10 @@ public class VisitImpl extends StoredExtensionType implements Visit {
public String getPatientId(){return patientId;} public String getPatientId(){return patientId;}
public void setPatientId(String patientId){ public void setPatient(Patient patient){
Objects.requireNonNull(patient);
// patient id should not be changed normally. // patient id should not be changed normally.
this.patientId = patientId; this.patientId = patient.getId();
// TODO need to update dirty flag? // TODO need to update dirty flag?
markDirty(true); markDirty(true);
} }
......
...@@ -2,6 +2,7 @@ package de.sekmi.histream.i2b2; ...@@ -2,6 +2,7 @@ package de.sekmi.histream.i2b2;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import de.sekmi.histream.ext.Patient;
import de.sekmi.histream.ext.Visit; import de.sekmi.histream.ext.Visit;
/* /*
...@@ -64,7 +65,17 @@ public class I2b2Visit extends VisitImpl { ...@@ -64,7 +65,17 @@ public class I2b2Visit extends VisitImpl {
public int getNum(){return encounter_num;} public int getNum(){return encounter_num;}
public int getPatientNum(){return patient_num;} public int getPatientNum(){return patient_num;}
@Override
public void setPatient(Patient patient) {
super.setPatient(patient);
if( patient instanceof I2b2Patient ) {
// also set the patient_num
int patient_num = ((I2b2Patient)patient).getNum();
this.patient_num = patient_num;
}
}
@Override @Override
public String toString(){ public String toString(){
return "I2b2Visit(encounter_um="+encounter_num+")"; return "I2b2Visit(encounter_um="+encounter_num+")";
......
...@@ -53,6 +53,7 @@ import de.sekmi.histream.ext.Visit.Status; ...@@ -53,6 +53,7 @@ import de.sekmi.histream.ext.Visit.Status;
* <p> * <p>
* Some optional columns are used: active_status_cd, start_date, end_date, inout_cd, location_cd, sourcesystem_cd * Some optional columns are used: active_status_cd, start_date, end_date, inout_cd, location_cd, sourcesystem_cd
* <p> * <p>
* XXX after loading encounters, the String patientId not set anymore and always null. To determine the patientId, the patientStore is required for lookup of the patientNum
* TODO use encounter_mapping table to map actual (source) patient_ide to internal patient_num for facts. * TODO use encounter_mapping table to map actual (source) patient_ide to internal patient_num for facts.
* <p> * <p>
* The variable argument list for {@link #createInstance(Object...)} requires the following arguments: * The variable argument list for {@link #createInstance(Object...)} requires the following arguments:
...@@ -137,14 +138,14 @@ public class PostgresVisitStore extends PostgresExtension<I2b2Visit> implements ...@@ -137,14 +138,14 @@ public class PostgresVisitStore extends PostgresExtension<I2b2Visit> implements
db.setAutoCommit(true); db.setAutoCommit(true);
prepareStatements(); prepareStatements();
loadMaxEncounterNum(); loadMaxEncounterNum();
batchLoad(); batchLoad(); /// XXX loading visits does not set the String patientId, for that, the patientStore would be needed
} }
@Override @Override
protected void prepareStatements() throws SQLException { protected void prepareStatements() throws SQLException {
// TODO: use prefix from configuration to specify tablespace // TODO: use prefix from configuration to specify tablespace
insert = db.prepareStatement("INSERT INTO visit_dimension(encounter_num, patient_num, import_date, download_date, sourcesystem_cd) VALUES(?,?,current_timestamp,?,?)"); insert = db.prepareStatement("INSERT INTO visit_dimension(encounter_num, patient_num, import_date, download_date, sourcesystem_cd) VALUES(?,?,current_timestamp,?,?)");
insertMapping = db.prepareStatement("INSERT INTO encounter_mapping(encounter_num, encounter_ide, encounter_ide_source, patient_ide, patient_ide_source, encounter_ide_status, project_id, import_date, download_date, sourcesystem_cd) VALUES(?,?,?,?,?,'A','"+projectId+"',current_timestamp,?,?)"); insertMapping = db.prepareStatement("INSERT INTO encounter_mapping(encounter_num, encounter_ide, encounter_ide_source, patient_ide, patient_ide_source, encounter_ide_status, project_id, import_date, download_date, sourcesystem_cd) VALUES(?,?,?,?,?,'A','"+projectId+"',current_timestamp,?,?)");
update = db.prepareStatement("UPDATE visit_dimension SET active_status_cd=?, start_date=?, end_date=?, inout_cd=?, location_cd=?, update_date=current_timestamp, download_date=?, sourcesystem_cd=? WHERE encounter_num=?"); update = db.prepareStatement("UPDATE visit_dimension SET patient_num=?, active_status_cd=?, start_date=?, end_date=?, inout_cd=?, location_cd=?, update_date=current_timestamp, download_date=?, sourcesystem_cd=? WHERE encounter_num=?");
//select = db.prepareStatement("SELECT encounter_num, patient_num, active_status_cd, start_date, end_date, inout_cd, location_cd, update_date, sourcesystem_cd FROM visit_dimension WHERE patient_num=?"); //select = db.prepareStatement("SELECT encounter_num, patient_num, active_status_cd, start_date, end_date, inout_cd, location_cd, update_date, sourcesystem_cd FROM visit_dimension WHERE patient_num=?");
selectAll = db.prepareStatement("SELECT encounter_num, patient_num, active_status_cd, start_date, end_date, inout_cd, location_cd, download_date, sourcesystem_cd FROM visit_dimension", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); selectAll = db.prepareStatement("SELECT encounter_num, patient_num, active_status_cd, start_date, end_date, inout_cd, location_cd, download_date, sourcesystem_cd FROM visit_dimension", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
selectAll.setFetchSize(fetchSize); selectAll.setFetchSize(fetchSize);
...@@ -310,16 +311,17 @@ public class PostgresVisitStore extends PostgresExtension<I2b2Visit> implements ...@@ -310,16 +311,17 @@ public class PostgresVisitStore extends PostgresExtension<I2b2Visit> implements
private void updateStorage(I2b2Visit visit) throws SQLException { private void updateStorage(I2b2Visit visit) throws SQLException {
synchronized( update ){ synchronized( update ){
update.setString(1, visit.getActiveStatusCd()); update.setInt(1, visit.getPatientNum());
update.setTimestamp(2, dialect.encodeInstantPartial(visit.getStartTime())); update.setString(2, visit.getActiveStatusCd());
update.setTimestamp(3, dialect.encodeInstantPartial(visit.getEndTime())); update.setTimestamp(3, dialect.encodeInstantPartial(visit.getStartTime()));
update.setString(4, visit.getInOutCd()); update.setTimestamp(4, dialect.encodeInstantPartial(visit.getEndTime()));
update.setString(5, dialect.encodeLocationCd(visit.getLocationId())); update.setString(5, visit.getInOutCd());
update.setTimestamp(6, dialect.encodeInstant(visit.getSourceTimestamp())); update.setString(6, dialect.encodeLocationCd(visit.getLocationId()));
update.setString(7, visit.getSourceId()); update.setTimestamp(7, dialect.encodeInstant(visit.getSourceTimestamp()));
update.setString(8, visit.getSourceId());
// where encounter_num=visit.getNum() // where encounter_num=visit.getNum()
update.setInt(8, visit.getNum()); update.setInt(9, visit.getNum());
int rows = update.executeUpdate(); int rows = update.executeUpdate();
if( rows == 0 ){ if( rows == 0 ){
log.warning("UPDATE executed for visit_dimension.encounter_num="+visit.getNum()+", but no rows changed."); log.warning("UPDATE executed for visit_dimension.encounter_num="+visit.getNum()+", but no rows changed.");
...@@ -368,7 +370,8 @@ public class PostgresVisitStore extends PostgresExtension<I2b2Visit> implements ...@@ -368,7 +370,8 @@ public class PostgresVisitStore extends PostgresExtension<I2b2Visit> implements
private I2b2Visit loadFromResultSet(ResultSet rs) throws SQLException{ private I2b2Visit loadFromResultSet(ResultSet rs) throws SQLException{
int id = rs.getInt(1); int id = rs.getInt(1);
int patid = rs.getInt(2); int patid = rs.getInt(2);
// XXX String patientId is always null after loading from the database.
// load vital status code, which contains information about // load vital status code, which contains information about
// accuracy of birth and death dates. // accuracy of birth and death dates.
String active_status_cd = rs.getString(3); String active_status_cd = rs.getString(3);
...@@ -426,10 +429,12 @@ public class PostgresVisitStore extends PostgresExtension<I2b2Visit> implements ...@@ -426,10 +429,12 @@ public class PostgresVisitStore extends PostgresExtension<I2b2Visit> implements
I2b2Visit visit = idCache.get(encounterId); I2b2Visit visit = idCache.get(encounterId);
if( visit == null ){ if( visit == null ){
// visit does not exist, create a new one
maxEncounterNum ++; maxEncounterNum ++;
int encounter_num = maxEncounterNum; int encounter_num = maxEncounterNum;
visit = new I2b2Visit(encounter_num, patient.getNum()); visit = new I2b2Visit(encounter_num, patient.getNum());
visit.setPatientId(patient.getId()); visit.setPatient(patient);
// created from observation, use source metadata // created from observation, use source metadata
visit.setSourceId(source.getSourceId()); visit.setSourceId(source.getSourceId());
...@@ -451,12 +456,17 @@ public class PostgresVisitStore extends PostgresExtension<I2b2Visit> implements ...@@ -451,12 +456,17 @@ public class PostgresVisitStore extends PostgresExtension<I2b2Visit> implements
// commonly, the item is modified after a call to this method, // commonly, the item is modified after a call to this method,
// but changes are written later via a call to update. // but changes are written later via a call to update.
// (otherwise, the instance would need to know whether to perform INSERT or UPDATE) // (otherwise, the instance would need to know whether to perform INSERT or UPDATE)
}else if( rejectPatientChange ){ }else {
// visit already existing // visit already existing
// verify that the patient number from the visit matches with the observation // verify that the patient number from the visit matches with the observation
if( visit.getPatientNum() != patient.getNum() ){ if( visit.getPatientNum() != patient.getNum() ){
// throw exception to abort processing // throw exception to abort processing
throw new AssertionError("Patient_num mismatch between observation and visit", null); if( rejectPatientChange ){
throw new AssertionError("Patient_num mismatch for visit "+encounterId+": history says "+visit.getPatientNum()+" while data says "+patient.getNum(), null);
}else {
log.info("Updating visit #"+visit.getNum()+" for patient change from #"+visit.getPatientNum()+" to #"+patient.getNum());
visit.setPatient(patient);
}
} }
} }
return visit; return visit;
......
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