Commit 76ba58c6 authored by R.W.Majeed's avatar R.W.Majeed

default local time zone can be specified in GroupedXMLReader. Tests for timestamp handling

parent 67e399fd
......@@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.text.ParseException;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.Map;
......@@ -29,6 +30,7 @@ import de.sekmi.histream.impl.ExternalSourceImpl;
import de.sekmi.histream.impl.Meta;
import de.sekmi.histream.impl.ObservationFactoryImpl;
import de.sekmi.histream.impl.ObservationImpl;
import de.sekmi.histream.xml.DateTimeAccuracyAdapter;
/**
* Read grouped observations from XML
......@@ -61,32 +63,50 @@ public class GroupedXMLReader implements ObservationSupplier {
private DateTimeAccuracy encounterStart;
private DateTimeAccuracy encounterEnd;
private Map<String,String> visitData;
private ZoneId zoneId;
public GroupedXMLReader(ObservationFactory factory, InputStream input)throws JAXBException, XMLStreamException, FactoryConfigurationError{
this(factory, input, null);
}
/**
* The provided {@code input} is not closed by a call to {@link #close()}
*
* @param factory observation factory
* @param input XML input
* @param localZone zone to use for local timestamps
* @throws JAXBException JAXB error
* @throws XMLStreamException XML stream error
* @throws FactoryConfigurationError other error
*/
public GroupedXMLReader(ObservationFactory factory, InputStream input)throws JAXBException, XMLStreamException, FactoryConfigurationError{
this(factory, XMLInputFactory.newInstance().createXMLStreamReader(input));
public GroupedXMLReader(ObservationFactory factory, InputStream input, ZoneId localZone)throws JAXBException, XMLStreamException, FactoryConfigurationError{
this(factory, XMLInputFactory.newInstance().createXMLStreamReader(input), localZone);
}
public GroupedXMLReader(ObservationFactory factory, XMLStreamReader reader) throws JAXBException, XMLStreamException{
this(factory,reader,null);
}
/**
* Construct a reader with a {@link XMLStreamReader}. The {@code reader} is closed when {@link #close()} is called.
* @param factory observation factory
* @param reader xml reader
* @param localZone zone to use for local timestamps
* @throws JAXBException jaxb error
* @throws XMLStreamException stream error
*/
public GroupedXMLReader(ObservationFactory factory, XMLStreamReader reader) throws JAXBException, XMLStreamException{
public GroupedXMLReader(ObservationFactory factory, XMLStreamReader reader, ZoneId localZone) throws JAXBException, XMLStreamException{
super();
this.factory = factory;
this.patientData = new HashMap<>();
this.visitData = new HashMap<>();
unmarshaller = JAXBContext.newInstance(ObservationImpl.class,Meta.class).createUnmarshaller();
this.zoneId = localZone;
if( zoneId != null ){
// modify marshaller to use the timezone for timestamps
DateTimeAccuracyAdapter a = new DateTimeAccuracyAdapter();
a.setZoneId(zoneId);
unmarshaller.setAdapter(DateTimeAccuracyAdapter.class, a);
}
// TODO: set schema
//unmarshaller.setSchema(schema);
this.reader = reader;
......@@ -103,7 +123,7 @@ public class GroupedXMLReader implements ObservationSupplier {
readPatient();
readEncounter();
}
private void readToRoot() throws XMLStreamException{
while( reader.hasNext() ){
reader.next();
......@@ -155,7 +175,7 @@ public class GroupedXMLReader implements ObservationSupplier {
if( patientData.containsKey("birthdate") ){
String dob = patientData.get("birthdate");
try {
currentPatient.setBirthDate(DateTimeAccuracy.parsePartialIso8601(dob));
currentPatient.setBirthDate(DateTimeAccuracy.parsePartialIso8601(dob, zoneId));
} catch (ParseException e) {
throw new XMLStreamException("Unable to parse birthdate: "+dob, reader.getLocation(), e);
}
......@@ -167,7 +187,7 @@ public class GroupedXMLReader implements ObservationSupplier {
// will be empty string for <deceased/>
if( date != null && date.length() != 0 ){
try {
currentPatient.setDeathDate(DateTimeAccuracy.parsePartialIso8601(date));
currentPatient.setDeathDate(DateTimeAccuracy.parsePartialIso8601(date, zoneId));
} catch (ParseException e) {
throw new XMLStreamException("Unable to parse deceased date: "+date, reader.getLocation(), e);
}
......@@ -238,7 +258,7 @@ public class GroupedXMLReader implements ObservationSupplier {
if( visitData.containsKey("start") ){
String date = visitData.get("start");
try {
encounterStart = DateTimeAccuracy.parsePartialIso8601(date);
encounterStart = DateTimeAccuracy.parsePartialIso8601(date, zoneId);
} catch (ParseException e) {
throw new XMLStreamException("Unable to parse encounter/start: "+date, reader.getLocation(), e);
}
......@@ -248,7 +268,7 @@ public class GroupedXMLReader implements ObservationSupplier {
if( visitData.containsKey("end") ){
String date = visitData.get("end");
try {
encounterEnd = DateTimeAccuracy.parsePartialIso8601(date);
encounterEnd = DateTimeAccuracy.parsePartialIso8601(date, zoneId);
} catch (ParseException e) {
throw new XMLStreamException("Unable to parse encounter/end: "+date, reader.getLocation(), e);
}
......
......@@ -31,8 +31,8 @@ public class DateTimeAccuracyAdapter extends XmlAdapter<String, DateTimeAccuracy
public DateTimeAccuracy unmarshal(String v) throws ParseException {
if( v == null )return null;
// parsing will support any zone offset
// TODO if zone is missing, assume specified zone
return DateTimeAccuracy.parsePartialIso8601(v);
// if zone is missing, assume specified zone
return DateTimeAccuracy.parsePartialIso8601(v, zoneId);
}
@Override
......
......@@ -32,6 +32,7 @@ import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import de.sekmi.histream.DateTimeAccuracy;
import de.sekmi.histream.ObservationException;
import de.sekmi.histream.ObservationSupplier;
import de.sekmi.histream.impl.ExternalSourceImpl;
......@@ -171,6 +172,7 @@ public class TestXMLWriter {
ObservationSupplier s = t.getExampleSupplier();
Document doc = createDocument();
GroupedXMLWriter w = new GroupedXMLWriter(new DOMResult(doc));
w.setZoneId(ZoneId.of("Asia/Shanghai"));
Meta.transfer(s, w);
Streams.transfer(s, w);
w.close();
......@@ -178,6 +180,8 @@ public class TestXMLWriter {
doc.normalizeDocument();
XMLUtils.printDOM(doc, debugLog);
// read back DOM
}
@Test
public void testWriteStream() throws Exception{
......@@ -192,15 +196,42 @@ public class TestXMLWriter {
}
@Test
public void testTimestampsWithZoneOffset() throws Exception{
ZoneId zone = ZoneId.of("Asia/Shanghai");
FileObservationProviderTest t = new FileObservationProviderTest();
t.initializeObservationFactory();
ObservationSupplier s = t.getExampleSupplier();
GroupedXMLWriter w = new GroupedXMLWriter(debugLog);
w.setZoneId(ZoneId.of("Asia/Shanghai"));
Meta.transfer(s, w);
Streams.transfer(s, w);
w.close();
s.close();
Path temp = Files.createTempFile("eav", ".xml");
try( OutputStream out = Files.newOutputStream(temp) ){
GroupedXMLWriter w = new GroupedXMLWriter(out);
w.setZoneId(zone);
Meta.transfer(s, w);
Streams.transfer(s, w);
w.close();
s.close();
}
System.out.println("XML output written to "+temp);
// read back XML
try( InputStream in = Files.newInputStream(temp) ){
GroupedXMLReader reader = new GroupedXMLReader(t.getFactory(), in);
Assert.assertEquals(DateTimeAccuracy.parsePartialIso8601("2014-09-07T18:40:03+0800"), reader.get().getStartTime());
reader.close();
}
// delete temp file
Files.delete(temp);
// read without zone
try( InputStream in = getClass().getResourceAsStream("/dwh.xml") ){
GroupedXMLReader reader = new GroupedXMLReader(t.getFactory(), in);
// local timestamps treated as UTC
Assert.assertEquals(DateTimeAccuracy.parsePartialIso8601("2014-09-07T18:40:03+0800"), reader.get().getStartTime());
reader.close();
}
try( InputStream in = getClass().getResourceAsStream("/dwh.xml") ){
// local timestamps treated as CST
GroupedXMLReader reader = new GroupedXMLReader(t.getFactory(), in, zone);
Assert.assertEquals(DateTimeAccuracy.parsePartialIso8601("2014-09-07T10:40:03+0800"), reader.get().getStartTime());
reader.close();
}
}
@Test
......
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