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; 054import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; 055 056public class ObservationStatsBuilder { 057 058 public static void main(String[] args) throws IOException, FHIRException { 059 buildVitalSignsSet(); 060 buildStatsSeries(); 061 062 } 063 064 private static void buildVitalSignsSet() throws IOException, FHIRFormatError { 065 Calendar base = Calendar.getInstance(); 066 base.add(Calendar.DAY_OF_MONTH, -1); 067 Bundle b = new Bundle(); 068 b.setType(BundleType.COLLECTION); 069 b.setId(UUID.randomUUID().toString().toLowerCase()); 070 071 vitals(b, base, 0, 80, 120, 95, 37.1); 072 vitals(b, base, 35, 85, 140, 98, 36.9); 073 vitals(b, base, 53, 75, 110, 96, 36.2); 074 vitals(b, base, 59, 65, 100, 94, 35.5); 075 vitals(b, base, 104, 60, 90, 90, 35.9); 076 vitals(b, base, 109, 65, 100, 92, 36.5); 077 vitals(b, base, 114, 70, 130, 94, 37.5); 078 vitals(b, base, 120, 90, 150, 97, 37.3); 079 vitals(b, base, 130, 95, 133, 97, 37.2); 080 vitals(b, base, 150, 85, 125, 98, 37.1); 081 082 new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path("[tmp]", "vitals.xml")), b); 083 } 084 085 private static void vitals(Bundle b, Calendar base, int minutes, int diastolic, int systolic, int sat, double temp) throws FHIRFormatError { 086 Calendar when = (Calendar) base.clone(); 087 when.add(Calendar.MINUTE, minutes); 088 089 baseVitals(b, when, minutes, "sat", "59408-5", "O2 Saturation").setValue(makeQty(sat, "%", "%")); 090 baseVitals(b, when, minutes, "temp", "8310-5", "Body temperature").setValue(makeQty(temp, "\u00b0C", "Cel")); 091 Observation obs = baseVitals(b, when, minutes, "bp", "85354-9", "Blood pressure"); 092 component(obs, "8480-6", "Systolic").setValue(makeQty(systolic, "mmhg", "mm[Hg]")); 093 component(obs, "8462-4", "Diastolic").setValue(makeQty(diastolic, "mmhg", "mm[Hg]")); 094 095 } 096 097 private static ObservationComponentComponent component(Observation obs, String lCode, String text) { 098 ObservationComponentComponent comp = obs.addComponent(); 099 comp.getCode().setText(text).addCoding().setCode(lCode).setSystem("http://loinc.org"); 100 return comp; 101 } 102 103 private static Type makeQty(int sat, String human, String ucum) { 104 Quantity q = new Quantity(); 105 q.setCode(ucum); 106 q.setSystem("http://unitsofmeasure.org"); 107 q.setUnit(human); 108 q.setValue(new BigDecimal(sat)); 109 return q; 110 } 111 112 113 private static Type makeQty(double val, String human, String ucum) { 114 Quantity q = new Quantity(); 115 q.setCode(ucum); 116 q.setSystem("http://unitsofmeasure.org"); 117 q.setUnit(human); 118 q.setValue(new BigDecimal(val)); 119 return q; 120 } 121 122 private static Observation baseVitals(Bundle b, Calendar when, int min, String name, String lCode, String text) throws FHIRFormatError { 123 Observation obs = new Observation(); 124 obs.setId("obs-vitals-" + name + "-" + min); 125 obs.setSubject(new Reference().setReference("Patient/123")); 126 obs.setStatus(ObservationStatus.FINAL); 127 obs.setEffective(new DateTimeType(when)); 128 obs.addCategory().setText("Vital Signs").addCoding().setSystem("http://hl7.org/fhir/observation-category").setCode("vital-signs").setDisplay("Vital Signs"); 129 obs.getCode().setText(text).addCoding().setCode(lCode).setSystem("http://loinc.org"); 130 b.addEntry().setFullUrl("http://hl7.org/fhir/Observation/" + obs.getId()).setResource(obs); 131 return obs; 132 } 133 134 /** 135 * @throws FHIRException 136 * @throws IOException 137 * @throws FileNotFoundException 138 */ 139 public static void buildStatsSeries() throws FHIRException, IOException, FileNotFoundException { 140 Bundle b = new Bundle(); 141 b.setType(BundleType.COLLECTION); 142 b.setId(UUID.randomUUID().toString().toLowerCase()); 143 144 addAge(b, 5, 1, "18.3"); 145 addAge(b, 5, 2, "18.4"); 146 addAge(b, 5, 3, "18.6"); 147 addAge(b, 5, 4, "18.8"); 148 addAge(b, 5, 5, "19.0"); 149 addAge(b, 5, 6, "19.1"); 150 addAge(b, 5, 7, "19.3"); 151 addAge(b, 5, 8, "19.5"); 152 addAge(b, 5, 9, "19.6"); 153 addAge(b, 5, 10, "19.8"); 154 addAge(b, 5, 11, "20.0"); 155 addAge(b, 6, 0, "20.2"); 156 addAge(b, 6, 1, "20.3"); 157 addAge(b, 6, 2, "20.5"); 158 addAge(b, 6, 3, "20.7"); 159 addAge(b, 6, 4, "20.9"); 160 addAge(b, 6, 5, "21.0"); 161 addAge(b, 6, 6, "21.2"); 162 addAge(b, 6, 7, "21.4"); 163 addAge(b, 6, 8, "21.6"); 164 addAge(b, 6, 9, "21.8"); 165 addAge(b, 6, 10, "22.0"); 166 addAge(b, 6, 11, "22.2"); 167 addAge(b, 7, 0, "22.4"); 168 addAge(b, 7, 1, "22.6"); 169 addAge(b, 7, 2, "22.8"); 170 addAge(b, 7, 3, "23.0"); 171 addAge(b, 7, 4, "23.2"); 172 addAge(b, 7, 5, "23.4"); 173 addAge(b, 7, 6, "23.6"); 174 addAge(b, 7, 7, "23.9"); 175 addAge(b, 7, 8, "24.1"); 176 addAge(b, 7, 9, "24.3"); 177 addAge(b, 7, 10, "24.5"); 178 addAge(b, 7, 11, "24.8"); 179 addAge(b, 8, 0, "25.0"); 180 addAge(b, 8, 1, "25.3"); 181 addAge(b, 8, 2, "25.5"); 182 addAge(b, 8, 3, "25.8"); 183 addAge(b, 8, 4, "26.0"); 184 addAge(b, 8, 5, "26.3"); 185 addAge(b, 8, 6, "26.6"); 186 addAge(b, 8, 7, "26.8"); 187 addAge(b, 8, 8, "27.1"); 188 addAge(b, 8, 9, "27.4"); 189 addAge(b, 8, 10, "27.6"); 190 addAge(b, 8, 11, "27.9"); 191 addAge(b, 9, 0, "28.2"); 192 addAge(b, 9, 1, "28.5"); 193 addAge(b, 9, 2, "28.8"); 194 addAge(b, 9, 3, "29.1"); 195 addAge(b, 9, 4, "29.4"); 196 addAge(b, 9, 5, "29.7"); 197 addAge(b, 9, 6, "30.0"); 198 addAge(b, 9, 7, "30.3"); 199 addAge(b, 9, 8, "30.6"); 200 addAge(b, 9, 9, "30.9"); 201 addAge(b, 9, 10, "31.2"); 202 addAge(b, 9, 11, "31.5"); 203 addAge(b, 10, 0, "31.9"); 204 205 206 new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path("[tmp]", "obs.xml")), b); 207 } 208 209 private static void addAge(Bundle b, int y, int m, String v) throws FHIRException { 210 Observation obs = new Observation(); 211 obs.setId("obs-example-age-weight-" + y + "-" + m); 212 obs.setSubject(new Reference().setReference("Patient/123")); 213 obs.setStatus(ObservationStatus.FINAL); 214 Calendar when = Calendar.getInstance(); 215 when.add(Calendar.YEAR, -y); 216 when.add(Calendar.MONTH, m); 217 obs.setEffective(new DateTimeType(when)); 218 obs.getCode().addCoding().setCode("29463-7").setSystem("http://loinc.org"); 219 obs.setValue(new Quantity()); 220 obs.getValueQuantity().setCode("kg"); 221 obs.getValueQuantity().setSystem("http://unitsofmeasure.org"); 222 obs.getValueQuantity().setUnit("kg"); 223 obs.getValueQuantity().setValue(new BigDecimal(v)); 224 b.addEntry().setFullUrl("http://hl7.org/fhir/Observation/" + obs.getId()).setResource(obs); 225 } 226 227}