Commit 50c48c53 authored by rwm's avatar rwm

source timestamp can be stored with patient and encounter in GroupedXMLReader/Writer

parent d3a8083f
Use GroupedXMLReader and GroupedXMLWriter write
external source information for patient.
Currently, this information is lost (e.g when loading from Import)
Write unit test to verify GroupedXMLWriter/Reader without meta_source meta_source_timestamp (=set to null)
......@@ -35,12 +35,14 @@
<gender>Female</gender>
<birthdate>2001-01-01</birthdate>
<deathdate>2020</deathdate>
<source timestamp="2015-09-28T09:41:10Z"/>
<encounter id="XXE12345">
<start>2014-01-01T10:30:00</start>
<end>2014-01-05T10:30:00</end>
<location>Zuhause</location>
<!-- TODO inpatient/outpatient
<provider>xxxa</provider>-->
<source timestamp="2015-09-28T08:41:10Z"/>
<facts>
<fact concept="T:date:secs" start="2014-09-07T10:40:03"/>
<fact concept="T:date:mins" start="2014-09-07T10:40"/>
......
......@@ -5,11 +5,13 @@ import java.time.Instant;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import de.sekmi.histream.ext.ExternalSourceType;
@XmlRootElement(name="source")
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
public class ExternalSourceImpl implements ExternalSourceType {
private Instant timestamp;
......
......@@ -11,6 +11,7 @@ import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
......@@ -23,6 +24,7 @@ import de.sekmi.histream.ext.ExternalSourceType;
import de.sekmi.histream.ext.Patient;
import de.sekmi.histream.ext.Patient.Sex;
import de.sekmi.histream.ext.Visit;
import de.sekmi.histream.impl.ExternalSourceImpl;
import de.sekmi.histream.impl.Meta;
import de.sekmi.histream.impl.ObservationFactoryImpl;
import de.sekmi.histream.impl.ObservationImpl;
......@@ -111,7 +113,8 @@ public class GroupedXMLReader implements ObservationSupplier {
patientData.clear();
reader.nextTag();
while( reader.isStartElement()
&& !reader.getLocalName().equals(ENCOUNTER_ELEMENT) )
&& !reader.getLocalName().equals(ENCOUNTER_ELEMENT)
&& !reader.getLocalName().equals("source") )
{
patientData.put(reader.getLocalName(), reader.getElementText());
reader.nextTag();
......@@ -134,6 +137,20 @@ public class GroupedXMLReader implements ObservationSupplier {
if( patientData.containsKey("given-name") ){
currentPatient.setGivenName(patientData.get("given-name"));
}
if( reader.getLocalName().equals("source") ){
ExternalSourceType es;
try {
es = (ExternalSourceType) unmarshaller.unmarshal(reader);
if( reader.getEventType() != XMLStreamConstants.START_ELEMENT ){
reader.nextTag();
}
} catch (JAXBException e) {
throw new XMLStreamException("Unable to parse patient source", reader.getLocation(), e);
}
if( es.getSourceTimestamp() != null ){
currentPatient.setSourceTimestamp(es.getSourceTimestamp());
}
}
}
/**
......@@ -150,7 +167,8 @@ public class GroupedXMLReader implements ObservationSupplier {
encounterId = reader.getAttributeValue(null, "id");
reader.nextTag();
while( reader.isStartElement()
&& !reader.getLocalName().equals(FACT_WRAPPER) )
&& !reader.getLocalName().equals(FACT_WRAPPER)
&& !reader.getLocalName().equals("source") )
{
visitData.put(reader.getLocalName(), reader.getElementText());
reader.nextTag();
......@@ -165,13 +183,31 @@ public class GroupedXMLReader implements ObservationSupplier {
}else{
encounterEnd = null;
}
ExternalSourceImpl es = null;
if( reader.getLocalName().equals("source") ){
try {
es = (ExternalSourceImpl) unmarshaller.unmarshal(reader);
if( reader.getEventType() != XMLStreamConstants.START_ELEMENT ){
reader.nextTag();
}
} catch (JAXBException e) {
throw new XMLStreamException("Unable to parse patient source", reader.getLocation(), e);
}
}
// TODO assert at <facts>
reader.nextTag();
currentVisit = visitAccessor.accessStatic(encounterId, currentPatient, (ExternalSourceType)meta.source);
currentVisit.setStartTime(encounterStart);
currentVisit.setEndTime(encounterEnd);
currentVisit.setLocationId(visitData.get("location"));
if( es != null ){
currentVisit.setSourceTimestamp(es.getSourceTimestamp());
}
// TODO set other visit data: gender, provider, in/out status
visitData.get("provider");
......
......@@ -17,6 +17,7 @@ import de.sekmi.histream.ObservationException;
import de.sekmi.histream.ext.ExternalSourceType;
import de.sekmi.histream.ext.Patient;
import de.sekmi.histream.ext.Visit;
import de.sekmi.histream.impl.ExternalSourceImpl;
import de.sekmi.histream.impl.GroupedObservationHandler;
import de.sekmi.histream.impl.Meta;
import de.sekmi.histream.impl.ObservationImpl;
......@@ -168,7 +169,14 @@ public class GroupedXMLWriter extends GroupedObservationHandler{
formatNewline();
}
// TODO implement provider
// write source timestamp
ExternalSourceImpl es = visitSourceWithContext(visit, meta.source);
if( es != null )try {
marshaller.marshal(es, writer);
} catch (JAXBException e) {
throw new ObservationException(e);
}
// TODO more data
formatIndent();
writer.writeStartElement(GroupedXMLReader.FACT_WRAPPER);
......@@ -260,11 +268,46 @@ public class GroupedXMLWriter extends GroupedObservationHandler{
writer.writeEndElement();
formatNewline();
}
// write source timestamp
ExternalSourceImpl es = patientSourceWithContext(patient,meta.source);
if( es != null )try {
marshaller.marshal(es, writer);
} catch (JAXBException e) {
throw new ObservationException(e);
}
// TODO use external source for patient
}catch( XMLStreamException e ){
throw new ObservationException(e);
}
}
private static ExternalSourceImpl patientSourceWithContext(Patient patient, ExternalSourceType context){
// TODO also write source id if different from meta
if( patient.getSourceTimestamp() != null
&& (context == null
|| context.getSourceTimestamp() == null
|| !patient.getSourceTimestamp().equals(context.getSourceTimestamp())) )
{
return new ExternalSourceImpl(null, patient.getSourceTimestamp());
}else{
return null;
}
}
private static ExternalSourceImpl visitSourceWithContext(Visit visit, ExternalSourceType context){
// TODO also write source id if different from meta
if( visit.getSourceTimestamp() != null
&& (context == null
|| context.getSourceTimestamp() == null
|| !visit.getSourceTimestamp().equals(context.getSourceTimestamp())) )
{
return new ExternalSourceImpl(null, visit.getSourceTimestamp());
}else{
return null;
}
}
/**
* Marshal a fact without writing context information from patient, visit and source.
*
......
Add flag to use direct patient numbers.
All patientIds are numeric and are converted to integer.
These integer ids are used directly in the patient table.
......@@ -10,6 +10,7 @@ import org.junit.Test;
import de.sekmi.histream.DateTimeAccuracy;
import de.sekmi.histream.Observation;
import de.sekmi.histream.ObservationSupplier;
import de.sekmi.histream.ext.ExternalSourceType;
import de.sekmi.histream.ext.Patient;
import de.sekmi.histream.ext.Visit;
import de.sekmi.histream.impl.Meta;
......@@ -36,7 +37,14 @@ public class TestETLSupplier {
Assert.assertNotNull(fact.getPatientId());
Assert.assertNotNull(fact.getStartTime());
Assert.assertNotNull(fact.getConceptId());
// source information
ExternalSourceType source = fact.getSource();
Assert.assertNotNull(source);
Assert.assertNotNull(source.getSourceId());
Assert.assertNotNull(source.getSourceTimestamp());
// next fact
fact = os.get();
}
}
......
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