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