
001package org.hl7.fhir.convertors.misc; 002 003import java.io.FileNotFoundException; 004import java.io.FileOutputStream; 005import java.io.IOException; 006import java.math.BigDecimal; 007import java.util.Calendar; 008import java.util.UUID; 009 010/* 011 Copyright (c) 2011+, HL7, Inc. 012 All rights reserved. 013 014 Redistribution and use in source and binary forms, with or without modification, 015 are permitted provided that the following conditions are met: 016 017 * Redistributions of source code must retain the above copyright notice, this 018 list of conditions and the following disclaimer. 019 * Redistributions in binary form must reproduce the above copyright notice, 020 this list of conditions and the following disclaimer in the documentation 021 and/or other materials provided with the distribution. 022 * Neither the name of HL7 nor the names of its contributors may be used to 023 endorse or promote products derived from this software without specific 024 prior written permission. 025 026 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 027 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 028 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 029 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 030 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 031 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 032 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 033 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 034 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 035 POSSIBILITY OF SUCH DAMAGE. 036 037 */ 038 039 040import org.hl7.fhir.dstu3.formats.IParser.OutputStyle; 041import org.hl7.fhir.dstu3.formats.XmlParser; 042import org.hl7.fhir.dstu3.model.Bundle; 043import org.hl7.fhir.dstu3.model.Bundle.BundleType; 044import org.hl7.fhir.dstu3.model.DateTimeType; 045import org.hl7.fhir.dstu3.model.Observation; 046import org.hl7.fhir.dstu3.model.Observation.ObservationComponentComponent; 047import org.hl7.fhir.dstu3.model.Observation.ObservationStatus; 048import org.hl7.fhir.dstu3.model.Quantity; 049import org.hl7.fhir.dstu3.model.Reference; 050import org.hl7.fhir.dstu3.model.Type; 051import org.hl7.fhir.exceptions.FHIRException; 052import org.hl7.fhir.exceptions.FHIRFormatError; 053import org.hl7.fhir.utilities.Utilities; 054 055public class ObservationStatsBuilder { 056 057 public static void main(String[] args) throws IOException, FHIRException { 058 buildVitalSignsSet(); 059 buildStatsSeries(); 060 061 } 062 063 private static void buildVitalSignsSet() throws IOException, FHIRFormatError { 064 Calendar base = Calendar.getInstance(); 065 base.add(Calendar.DAY_OF_MONTH, -1); 066 Bundle b = new Bundle(); 067 b.setType(BundleType.COLLECTION); 068 b.setId(UUID.randomUUID().toString().toLowerCase()); 069 070 vitals(b, base, 0, 80, 120, 95, 37.1); 071 vitals(b, base, 35, 85, 140, 98, 36.9); 072 vitals(b, base, 53, 75, 110, 96, 36.2); 073 vitals(b, base, 59, 65, 100, 94, 35.5); 074 vitals(b, base, 104, 60, 90, 90, 35.9); 075 vitals(b, base, 109, 65, 100, 92, 36.5); 076 vitals(b, base, 114, 70, 130, 94, 37.5); 077 vitals(b, base, 120, 90, 150, 97, 37.3); 078 vitals(b, base, 130, 95, 133, 97, 37.2); 079 vitals(b, base, 150, 85, 125, 98, 37.1); 080 081 new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "vitals.xml")), b); 082 } 083 084 private static void vitals(Bundle b, Calendar base, int minutes, int diastolic, int systolic, int sat, double temp) throws FHIRFormatError { 085 Calendar when = (Calendar) base.clone(); 086 when.add(Calendar.MINUTE, minutes); 087 088 baseVitals(b, when, minutes, "sat", "59408-5", "O2 Saturation").setValue(makeQty(sat, "%", "%")); 089 baseVitals(b, when, minutes, "temp", "8310-5", "Body temperature").setValue(makeQty(temp, "\u00b0C", "Cel")); 090 Observation obs = baseVitals(b, when, minutes, "bp", "85354-9", "Blood pressure"); 091 component(obs, "8480-6", "Systolic").setValue(makeQty(systolic, "mmhg", "mm[Hg]")); 092 component(obs, "8462-4", "Diastolic").setValue(makeQty(diastolic, "mmhg", "mm[Hg]")); 093 094 } 095 096 private static ObservationComponentComponent component(Observation obs, String lCode, String text) { 097 ObservationComponentComponent comp = obs.addComponent(); 098 comp.getCode().setText(text).addCoding().setCode(lCode).setSystem("http://loinc.org"); 099 return comp; 100 } 101 102 private static Type makeQty(int sat, String human, String ucum) { 103 Quantity q = new Quantity(); 104 q.setCode(ucum); 105 q.setSystem("http://unitsofmeasure.org"); 106 q.setUnit(human); 107 q.setValue(new BigDecimal(sat)); 108 return q; 109 } 110 111 112 private static Type makeQty(double val, String human, String ucum) { 113 Quantity q = new Quantity(); 114 q.setCode(ucum); 115 q.setSystem("http://unitsofmeasure.org"); 116 q.setUnit(human); 117 q.setValue(new BigDecimal(val)); 118 return q; 119 } 120 121 private static Observation baseVitals(Bundle b, Calendar when, int min, String name, String lCode, String text) throws FHIRFormatError { 122 Observation obs = new Observation(); 123 obs.setId("obs-vitals-" + name + "-" + min); 124 obs.setSubject(new Reference().setReference("Patient/123")); 125 obs.setStatus(ObservationStatus.FINAL); 126 obs.setEffective(new DateTimeType(when)); 127 obs.addCategory().setText("Vital Signs").addCoding().setSystem("http://hl7.org/fhir/observation-category").setCode("vital-signs").setDisplay("Vital Signs"); 128 obs.getCode().setText(text).addCoding().setCode(lCode).setSystem("http://loinc.org"); 129 b.addEntry().setFullUrl("http://hl7.org/fhir/Observation/" + obs.getId()).setResource(obs); 130 return obs; 131 } 132 133 /** 134 * @throws FHIRException 135 * @throws IOException 136 * @throws FileNotFoundException 137 */ 138 public static void buildStatsSeries() throws FHIRException, IOException, FileNotFoundException { 139 Bundle b = new Bundle(); 140 b.setType(BundleType.COLLECTION); 141 b.setId(UUID.randomUUID().toString().toLowerCase()); 142 143 addAge(b, 5, 1, "18.3"); 144 addAge(b, 5, 2, "18.4"); 145 addAge(b, 5, 3, "18.6"); 146 addAge(b, 5, 4, "18.8"); 147 addAge(b, 5, 5, "19.0"); 148 addAge(b, 5, 6, "19.1"); 149 addAge(b, 5, 7, "19.3"); 150 addAge(b, 5, 8, "19.5"); 151 addAge(b, 5, 9, "19.6"); 152 addAge(b, 5, 10, "19.8"); 153 addAge(b, 5, 11, "20.0"); 154 addAge(b, 6, 0, "20.2"); 155 addAge(b, 6, 1, "20.3"); 156 addAge(b, 6, 2, "20.5"); 157 addAge(b, 6, 3, "20.7"); 158 addAge(b, 6, 4, "20.9"); 159 addAge(b, 6, 5, "21.0"); 160 addAge(b, 6, 6, "21.2"); 161 addAge(b, 6, 7, "21.4"); 162 addAge(b, 6, 8, "21.6"); 163 addAge(b, 6, 9, "21.8"); 164 addAge(b, 6, 10, "22.0"); 165 addAge(b, 6, 11, "22.2"); 166 addAge(b, 7, 0, "22.4"); 167 addAge(b, 7, 1, "22.6"); 168 addAge(b, 7, 2, "22.8"); 169 addAge(b, 7, 3, "23.0"); 170 addAge(b, 7, 4, "23.2"); 171 addAge(b, 7, 5, "23.4"); 172 addAge(b, 7, 6, "23.6"); 173 addAge(b, 7, 7, "23.9"); 174 addAge(b, 7, 8, "24.1"); 175 addAge(b, 7, 9, "24.3"); 176 addAge(b, 7, 10, "24.5"); 177 addAge(b, 7, 11, "24.8"); 178 addAge(b, 8, 0, "25.0"); 179 addAge(b, 8, 1, "25.3"); 180 addAge(b, 8, 2, "25.5"); 181 addAge(b, 8, 3, "25.8"); 182 addAge(b, 8, 4, "26.0"); 183 addAge(b, 8, 5, "26.3"); 184 addAge(b, 8, 6, "26.6"); 185 addAge(b, 8, 7, "26.8"); 186 addAge(b, 8, 8, "27.1"); 187 addAge(b, 8, 9, "27.4"); 188 addAge(b, 8, 10, "27.6"); 189 addAge(b, 8, 11, "27.9"); 190 addAge(b, 9, 0, "28.2"); 191 addAge(b, 9, 1, "28.5"); 192 addAge(b, 9, 2, "28.8"); 193 addAge(b, 9, 3, "29.1"); 194 addAge(b, 9, 4, "29.4"); 195 addAge(b, 9, 5, "29.7"); 196 addAge(b, 9, 6, "30.0"); 197 addAge(b, 9, 7, "30.3"); 198 addAge(b, 9, 8, "30.6"); 199 addAge(b, 9, 9, "30.9"); 200 addAge(b, 9, 10, "31.2"); 201 addAge(b, 9, 11, "31.5"); 202 addAge(b, 10, 0, "31.9"); 203 204 205 new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "obs.xml")), b); 206 } 207 208 private static void addAge(Bundle b, int y, int m, String v) throws FHIRException { 209 Observation obs = new Observation(); 210 obs.setId("obs-example-age-weight-" + y + "-" + m); 211 obs.setSubject(new Reference().setReference("Patient/123")); 212 obs.setStatus(ObservationStatus.FINAL); 213 Calendar when = Calendar.getInstance(); 214 when.add(Calendar.YEAR, -y); 215 when.add(Calendar.MONTH, m); 216 obs.setEffective(new DateTimeType(when)); 217 obs.getCode().addCoding().setCode("29463-7").setSystem("http://loinc.org"); 218 obs.setValue(new Quantity()); 219 obs.getValueQuantity().setCode("kg"); 220 obs.getValueQuantity().setSystem("http://unitsofmeasure.org"); 221 obs.getValueQuantity().setUnit("kg"); 222 obs.getValueQuantity().setValue(new BigDecimal(v)); 223 b.addEntry().setFullUrl("http://hl7.org/fhir/Observation/" + obs.getId()).setResource(obs); 224 } 225 226}