Loading histream-import/src/main/java/de/sekmi/histream/etl/ColumnMap.java +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ public class ColumnMap{ Objects.requireNonNull(column); column.validate(); // TODO: maybe call after unmarshal of column if( column.getName().isEmpty() ){ if( column.getName() == null || column.getName().isEmpty() ){ // no reference to column, probably constant value // no need to register return; Loading histream-import/src/main/java/de/sekmi/histream/etl/config/Column.java +8 −7 Original line number Diff line number Diff line Loading @@ -5,7 +5,6 @@ import java.util.Objects; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlValue; import de.sekmi.histream.etl.ColumnMap; import de.sekmi.histream.etl.ParseException; Loading @@ -25,7 +24,7 @@ public abstract class Column<T> { } public Column(String name){ this(); this.name = name; this.column = name; } /** * If this string is found in the column data, the resulting value will be null. Loading Loading @@ -70,14 +69,14 @@ public abstract class Column<T> { /** * Column name to use for reading input values. */ @XmlValue String name; @XmlAttribute String column; /** * Column name to use for reading input values * @return column name */ public String getName(){return name;} public String getName(){return column;} public abstract T valueOf(Object input) throws ParseException; Loading Loading @@ -113,7 +112,7 @@ public abstract class Column<T> { } public T valueOf(ColumnMap map, Object[] row) throws ParseException{ if( name.isEmpty() ){ if( column == null || column.isEmpty() ){ // use constant value if available return valueOf(null); } Loading @@ -130,8 +129,10 @@ public abstract class Column<T> { } public void validate()throws ParseException{ if( name.isEmpty() && constantValue == null ){ if( column == null && constantValue == null ){ throw new ParseException("Empty column name only allowed if constant-value is specified"); }else if( column != null && column.isEmpty() ){ throw new ParseException("No empty column attribute allowed. Remove attribute for constant values"); } } } histream-import/src/main/java/de/sekmi/histream/etl/config/Concept.java +4 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,10 @@ public class Concept{ // numeric NumericValue v = new NumericValue((BigDecimal)value,unit); o.setValue(v); }else if( value instanceof Long ){ // numeric NumericValue v = new NumericValue((Long)value,unit); o.setValue(v); }else{ throw new ParseException("Unsupported value type for concept id "+this.id+": "+value.getClass()); } Loading histream-import/src/test/java/de/sekmi/histream/etl/config/TestMarshall.java +10 −10 Original line number Diff line number Diff line Loading @@ -27,33 +27,33 @@ public class TestMarshall { Assert.assertNotNull(ds.patientTable.source); Assert.assertEquals("\\t", ((FileSource)ds.patientTable.source).separator); Assert.assertNotNull(ds.patientTable.idat); Assert.assertEquals("patid",ds.patientTable.idat.patientId.name); Assert.assertEquals("geburtsdatum",ds.patientTable.idat.birthdate.name); Assert.assertEquals("geschlecht",ds.patientTable.idat.gender.name); Assert.assertEquals("vorname",ds.patientTable.idat.givenName.name); Assert.assertEquals("nachname",ds.patientTable.idat.surname.name); Assert.assertEquals("patid",ds.patientTable.idat.patientId.column); Assert.assertEquals("geburtsdatum",ds.patientTable.idat.birthdate.column); Assert.assertEquals("geschlecht",ds.patientTable.idat.gender.column); Assert.assertEquals("vorname",ds.patientTable.idat.givenName.column); Assert.assertEquals("nachname",ds.patientTable.idat.surname.column); // visit table Assert.assertNotNull(ds.visitTable); Assert.assertNotNull(ds.visitTable.source); Assert.assertNotNull(ds.visitTable.idat); Assert.assertEquals("patid",ds.visitTable.idat.patientId.name); Assert.assertEquals("fallnr",ds.visitTable.idat.visitId.name); Assert.assertEquals("patid",ds.visitTable.idat.patientId.column); Assert.assertEquals("fallnr",ds.visitTable.idat.visitId.column); // wide table Assert.assertNotNull(ds.wideTables); Assert.assertEquals(1, ds.wideTables.length); WideTable t = ds.wideTables[0]; Assert.assertNotNull(t); Assert.assertNotNull(t.idat); Assert.assertEquals("patid",t.idat.patientId.name); Assert.assertEquals("fallnr",t.idat.visitId.name); Assert.assertEquals("patid",t.idat.patientId.column); Assert.assertEquals("fallnr",t.idat.visitId.column); // concepts Assert.assertNotNull(t.concepts); Assert.assertTrue(t.concepts.length > 0); Concept c = t.concepts[0]; Assert.assertNotNull(c); Assert.assertEquals("natrium", c.id); Assert.assertEquals("na", c.value.name); Assert.assertEquals("na", c.value.column); Assert.assertEquals("mmol/l", c.unit.constantValue); } } Loading histream-import/src/test/resources/data/test-1-datasource.xml +36 −30 Original line number Diff line number Diff line Loading @@ -11,14 +11,20 @@ <separator>\t</separator> </source> <idat> <patient-id>patid</patient-id> <given-name>vorname</given-name> <surname>nachname</surname> <birthdate format="d.M.u" na="">geburtsdatum</birthdate> <deathdate format="d.M.u" na="">verstorben</deathdate> <gender>geschlecht</gender> <ignore xsi:type="string">ignoriert1</ignore> <ignore xsi:type="string">patfakt1</ignore> <patient-id column="patid"/> <given-name column="vorname"/> <surname column="nachname"/> <birthdate format="d.M.u" na="" column="geburtsdatum"/> <deathdate format="d.M.u" na="" column="verstorben"/> <gender column="geschlecht"> <map> <map if-value="W" set-value="F"/> <map if-value="M" set-value="M"/> <otherwise set-value=""/> </map> </gender> <ignore xsi:type="string" column="ignoriert1"/> <ignore xsi:type="string" column="patfakt1"/> </idat> <!-- for MDAT in patient table, use the same patient-table also as a visit table (visit date needed). the patient id can be re-used Loading @@ -32,17 +38,17 @@ <separator>\t</separator> </source> <idat> <patient-id>patid</patient-id> <visit-id>fallnr</visit-id> <start format="d.M.u[ H[:m[:s]]]" na="" truncate-to="year">start</start> <end format="d.M.u[ H[:m[:s]]]" na="">end</end> <patient-id column="patid"/> <visit-id column="fallnr"/> <start column="start" format="d.M.u[ H[:m[:s]]]" na="" truncate-to="year"/> <end column="end" format="d.M.u[ H[:m[:s]]]" na=""/> </idat> <mdat> <!-- in/out code --> <concept id="weight"> <value xsi:type="string">gewicht</value> <value column="gewicht" xsi:type="string"/> <!-- TODO: verify that na values are no allowed for concept start timestamps --> <start format="d.M.u[ H[:m[:s]]]" na="">start</start> <start column="start" format="d.M.u[ H[:m[:s]]]" na=""/> </concept> </mdat> </visit-table> Loading @@ -52,21 +58,21 @@ <separator>\t</separator> </source> <idat> <patient-id>patid</patient-id> <visit-id>fallnr</visit-id> <patient-id column="patid"/> <visit-id column="fallnr"/> </idat> <mdat> <concept id="natrium"> <value xsi:type="decimal">na</value> <start format="d.M.u[ H[:m[:s]]]">zeitpunkt</start> <value column="na" xsi:type="decimal"/> <start column="zeitpunkt" format="d.M.u[ H[:m[:s]]]"/> <unit constant-value="mmol/l" /> <modifier id="other"> <value xsi:type="string" constant-value=""/> </modifier> </concept> <concept id="kalium"> <value xsi:type="decimal">k</value> <start format="d.M.u[ H[:m[:s]]]">zeitpunkt</start> <value column="k" xsi:type="decimal"/> <start column="zeitpunkt" format="d.M.u[ H[:m[:s]]]"/> </concept> </mdat> Loading @@ -77,19 +83,19 @@ <separator>\t</separator> </source> <idat> <patient-id>patid</patient-id> <visit-id>event</visit-id> <ignore xsi:type="string">locat</ignore> <ignore xsi:type="string">user</ignore> <patient-id column="patid"/> <visit-id column="event"/> <ignore column="locat" xsi:type="string"/> <ignore column="user" xsi:type="string"/> </idat> <mdat> <concept>param</concept> <start format="u-M-d">start_ts</start> <end format="u-M-d" na="@">end</end> <concept column="param"/> <start column="start_ts" format="u-M-d"/> <end column="end" format="u-M-d" na="@"/> <!-- location --> <type>type</type> <value na="@">value</value> <unit na="@">unit</unit> <type column="type"/> <value column="value" na="@"/> <unit column="unit" na="@"/> </mdat> </eav-table> Loading Loading
histream-import/src/main/java/de/sekmi/histream/etl/ColumnMap.java +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ public class ColumnMap{ Objects.requireNonNull(column); column.validate(); // TODO: maybe call after unmarshal of column if( column.getName().isEmpty() ){ if( column.getName() == null || column.getName().isEmpty() ){ // no reference to column, probably constant value // no need to register return; Loading
histream-import/src/main/java/de/sekmi/histream/etl/config/Column.java +8 −7 Original line number Diff line number Diff line Loading @@ -5,7 +5,6 @@ import java.util.Objects; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlValue; import de.sekmi.histream.etl.ColumnMap; import de.sekmi.histream.etl.ParseException; Loading @@ -25,7 +24,7 @@ public abstract class Column<T> { } public Column(String name){ this(); this.name = name; this.column = name; } /** * If this string is found in the column data, the resulting value will be null. Loading Loading @@ -70,14 +69,14 @@ public abstract class Column<T> { /** * Column name to use for reading input values. */ @XmlValue String name; @XmlAttribute String column; /** * Column name to use for reading input values * @return column name */ public String getName(){return name;} public String getName(){return column;} public abstract T valueOf(Object input) throws ParseException; Loading Loading @@ -113,7 +112,7 @@ public abstract class Column<T> { } public T valueOf(ColumnMap map, Object[] row) throws ParseException{ if( name.isEmpty() ){ if( column == null || column.isEmpty() ){ // use constant value if available return valueOf(null); } Loading @@ -130,8 +129,10 @@ public abstract class Column<T> { } public void validate()throws ParseException{ if( name.isEmpty() && constantValue == null ){ if( column == null && constantValue == null ){ throw new ParseException("Empty column name only allowed if constant-value is specified"); }else if( column != null && column.isEmpty() ){ throw new ParseException("No empty column attribute allowed. Remove attribute for constant values"); } } }
histream-import/src/main/java/de/sekmi/histream/etl/config/Concept.java +4 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,10 @@ public class Concept{ // numeric NumericValue v = new NumericValue((BigDecimal)value,unit); o.setValue(v); }else if( value instanceof Long ){ // numeric NumericValue v = new NumericValue((Long)value,unit); o.setValue(v); }else{ throw new ParseException("Unsupported value type for concept id "+this.id+": "+value.getClass()); } Loading
histream-import/src/test/java/de/sekmi/histream/etl/config/TestMarshall.java +10 −10 Original line number Diff line number Diff line Loading @@ -27,33 +27,33 @@ public class TestMarshall { Assert.assertNotNull(ds.patientTable.source); Assert.assertEquals("\\t", ((FileSource)ds.patientTable.source).separator); Assert.assertNotNull(ds.patientTable.idat); Assert.assertEquals("patid",ds.patientTable.idat.patientId.name); Assert.assertEquals("geburtsdatum",ds.patientTable.idat.birthdate.name); Assert.assertEquals("geschlecht",ds.patientTable.idat.gender.name); Assert.assertEquals("vorname",ds.patientTable.idat.givenName.name); Assert.assertEquals("nachname",ds.patientTable.idat.surname.name); Assert.assertEquals("patid",ds.patientTable.idat.patientId.column); Assert.assertEquals("geburtsdatum",ds.patientTable.idat.birthdate.column); Assert.assertEquals("geschlecht",ds.patientTable.idat.gender.column); Assert.assertEquals("vorname",ds.patientTable.idat.givenName.column); Assert.assertEquals("nachname",ds.patientTable.idat.surname.column); // visit table Assert.assertNotNull(ds.visitTable); Assert.assertNotNull(ds.visitTable.source); Assert.assertNotNull(ds.visitTable.idat); Assert.assertEquals("patid",ds.visitTable.idat.patientId.name); Assert.assertEquals("fallnr",ds.visitTable.idat.visitId.name); Assert.assertEquals("patid",ds.visitTable.idat.patientId.column); Assert.assertEquals("fallnr",ds.visitTable.idat.visitId.column); // wide table Assert.assertNotNull(ds.wideTables); Assert.assertEquals(1, ds.wideTables.length); WideTable t = ds.wideTables[0]; Assert.assertNotNull(t); Assert.assertNotNull(t.idat); Assert.assertEquals("patid",t.idat.patientId.name); Assert.assertEquals("fallnr",t.idat.visitId.name); Assert.assertEquals("patid",t.idat.patientId.column); Assert.assertEquals("fallnr",t.idat.visitId.column); // concepts Assert.assertNotNull(t.concepts); Assert.assertTrue(t.concepts.length > 0); Concept c = t.concepts[0]; Assert.assertNotNull(c); Assert.assertEquals("natrium", c.id); Assert.assertEquals("na", c.value.name); Assert.assertEquals("na", c.value.column); Assert.assertEquals("mmol/l", c.unit.constantValue); } } Loading
histream-import/src/test/resources/data/test-1-datasource.xml +36 −30 Original line number Diff line number Diff line Loading @@ -11,14 +11,20 @@ <separator>\t</separator> </source> <idat> <patient-id>patid</patient-id> <given-name>vorname</given-name> <surname>nachname</surname> <birthdate format="d.M.u" na="">geburtsdatum</birthdate> <deathdate format="d.M.u" na="">verstorben</deathdate> <gender>geschlecht</gender> <ignore xsi:type="string">ignoriert1</ignore> <ignore xsi:type="string">patfakt1</ignore> <patient-id column="patid"/> <given-name column="vorname"/> <surname column="nachname"/> <birthdate format="d.M.u" na="" column="geburtsdatum"/> <deathdate format="d.M.u" na="" column="verstorben"/> <gender column="geschlecht"> <map> <map if-value="W" set-value="F"/> <map if-value="M" set-value="M"/> <otherwise set-value=""/> </map> </gender> <ignore xsi:type="string" column="ignoriert1"/> <ignore xsi:type="string" column="patfakt1"/> </idat> <!-- for MDAT in patient table, use the same patient-table also as a visit table (visit date needed). the patient id can be re-used Loading @@ -32,17 +38,17 @@ <separator>\t</separator> </source> <idat> <patient-id>patid</patient-id> <visit-id>fallnr</visit-id> <start format="d.M.u[ H[:m[:s]]]" na="" truncate-to="year">start</start> <end format="d.M.u[ H[:m[:s]]]" na="">end</end> <patient-id column="patid"/> <visit-id column="fallnr"/> <start column="start" format="d.M.u[ H[:m[:s]]]" na="" truncate-to="year"/> <end column="end" format="d.M.u[ H[:m[:s]]]" na=""/> </idat> <mdat> <!-- in/out code --> <concept id="weight"> <value xsi:type="string">gewicht</value> <value column="gewicht" xsi:type="string"/> <!-- TODO: verify that na values are no allowed for concept start timestamps --> <start format="d.M.u[ H[:m[:s]]]" na="">start</start> <start column="start" format="d.M.u[ H[:m[:s]]]" na=""/> </concept> </mdat> </visit-table> Loading @@ -52,21 +58,21 @@ <separator>\t</separator> </source> <idat> <patient-id>patid</patient-id> <visit-id>fallnr</visit-id> <patient-id column="patid"/> <visit-id column="fallnr"/> </idat> <mdat> <concept id="natrium"> <value xsi:type="decimal">na</value> <start format="d.M.u[ H[:m[:s]]]">zeitpunkt</start> <value column="na" xsi:type="decimal"/> <start column="zeitpunkt" format="d.M.u[ H[:m[:s]]]"/> <unit constant-value="mmol/l" /> <modifier id="other"> <value xsi:type="string" constant-value=""/> </modifier> </concept> <concept id="kalium"> <value xsi:type="decimal">k</value> <start format="d.M.u[ H[:m[:s]]]">zeitpunkt</start> <value column="k" xsi:type="decimal"/> <start column="zeitpunkt" format="d.M.u[ H[:m[:s]]]"/> </concept> </mdat> Loading @@ -77,19 +83,19 @@ <separator>\t</separator> </source> <idat> <patient-id>patid</patient-id> <visit-id>event</visit-id> <ignore xsi:type="string">locat</ignore> <ignore xsi:type="string">user</ignore> <patient-id column="patid"/> <visit-id column="event"/> <ignore column="locat" xsi:type="string"/> <ignore column="user" xsi:type="string"/> </idat> <mdat> <concept>param</concept> <start format="u-M-d">start_ts</start> <end format="u-M-d" na="@">end</end> <concept column="param"/> <start column="start_ts" format="u-M-d"/> <end column="end" format="u-M-d" na="@"/> <!-- location --> <type>type</type> <value na="@">value</value> <unit na="@">unit</unit> <type column="type"/> <value column="value" na="@"/> <unit column="unit" na="@"/> </mdat> </eav-table> Loading