001package org.hl7.fhir.convertors.misc; 002 003 004 005 006 007/* 008 Copyright (c) 2011+, HL7, Inc. 009 All rights reserved. 010 011 Redistribution and use in source and binary forms, with or without modification, 012 are permitted provided that the following conditions are met: 013 014 * Redistributions of source code must retain the above copyright notice, this 015 list of conditions and the following disclaimer. 016 * Redistributions in binary form must reproduce the above copyright notice, 017 this list of conditions and the following disclaimer in the documentation 018 and/or other materials provided with the distribution. 019 * Neither the name of HL7 nor the names of its contributors may be used to 020 endorse or promote products derived from this software without specific 021 prior written permission. 022 023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 024 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 025 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 026 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 027 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 028 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 029 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 030 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 031 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 032 POSSIBILITY OF SUCH DAMAGE. 033 034*/ 035 036 037import org.fhir.ucum.UcumService; 038import org.hl7.fhir.dstu3.model.*; 039import org.hl7.fhir.dstu3.model.Address.AddressUse; 040import org.hl7.fhir.dstu3.model.ContactPoint.ContactPointSystem; 041import org.hl7.fhir.dstu3.model.ContactPoint.ContactPointUse; 042import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender; 043import org.hl7.fhir.dstu3.model.HumanName.NameUse; 044import org.hl7.fhir.dstu3.model.Timing.EventTiming; 045import org.hl7.fhir.dstu3.model.Timing.TimingRepeatComponent; 046import org.hl7.fhir.dstu3.model.Timing.UnitsOfTime; 047import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; 048import org.hl7.fhir.utilities.OIDUtils; 049import org.hl7.fhir.utilities.Utilities; 050import org.w3c.dom.Element; 051import org.w3c.dom.Node; 052 053import java.math.BigDecimal; 054import java.util.HashSet; 055import java.util.List; 056import java.util.Set; 057import java.util.UUID; 058 059public class Convert { 060 061 private final CDAUtilities cda; 062 private final UcumService ucumSvc; 063 private final Set<String> oids = new HashSet<String>(); 064 private final String defaultTimezone; 065 private boolean generateMissingExtensions; 066 067 public Convert(CDAUtilities cda, UcumService ucumSvc, String defaultTimezone) { 068 super(); 069 this.cda = cda; 070 this.ucumSvc = ucumSvc; 071 this.defaultTimezone = defaultTimezone; 072 } 073 074 public Identifier makeIdentifierFromII(Element e) throws Exception { 075 Identifier id = new Identifier(); 076 String r = e.getAttribute("root"); 077 String ex; 078 if (e.hasAttribute("extension") && Utilities.noString(e.getAttribute("extension"))) { 079 if (generateMissingExtensions) 080 ex = UUID.randomUUID().toString(); 081 else 082 throw new Exception("Broken identifier - extension is blank"); 083 } else 084 ex = e.getAttribute("extension"); 085 086 if (Utilities.noString(ex)) { 087 id.setSystem("urn:ietf:rfc:3986"); 088 if (isGuid(r)) 089 id.setValue("urn:uuid:" + r); 090 else if (UriForOid(r) != null) 091 id.setValue(UriForOid(r)); 092 else 093 id.setValue(UriForOid(r)); 094 } else { 095 if (isGuid(r)) 096 id.setSystem("urn:uuid:" + r); 097 else if (UriForOid(r) != null) 098 id.setSystem(UriForOid(r)); 099 else 100 id.setSystem("urn:oid:" + r); 101 id.setValue(ex); 102 } 103 return id; 104 } 105 106 public String makeURIfromII(Element e) { 107 String r = e.getAttribute("root"); 108 if (Utilities.noString(e.getAttribute("extension"))) { 109 if (isGuid(r)) 110 return "urn:uuid:" + r; 111 else if (UriForOid(r) != null) 112 return UriForOid(r); 113 else 114 return UriForOid(r); 115 } else { 116 if (isGuid(r)) 117 return "urn:uuid:" + r + "::" + e.getAttribute("extension"); 118 else if (UriForOid(r) != null) 119 return UriForOid(r) + "::" + e.getAttribute("extension"); 120 else 121 return "urn:oid:" + r + "::" + e.getAttribute("extension"); 122 } 123 } 124 125 private String UriForOid(String r) { 126 String uri = OIDUtils.getUriForOid(r); 127 if (uri != null) 128 return uri; 129 else { 130 oids.add(r); 131 return "urn:oid:" + r; 132 } 133 } 134 135 public boolean isGuid(String r) { 136 return r.matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"); 137 } 138 139 public InstantType makeInstantFromTS(Element child) throws Exception { 140 InstantType i = InstantType.parseV3(child.getAttribute("value")); 141 return i; 142 } 143 144 public CodeableConcept makeCodeableConceptFromCD(Element cv) throws Exception { 145 if (cv == null) 146 return null; 147 CodeableConcept cc = new CodeableConcept(); 148 cc.addCoding(makeCodingFromCV(cv)); 149 for (Element e : cda.getChildren(cv, "translation")) 150 cc.addCoding(makeCodingFromCV(e)); 151 if (cda.getChild(cv, "originalText") != null) { 152 Element ote = cda.getChild(cv, "originalText"); 153// if (cda.getChild(ote, "reference") != null) { 154// if (cda.getChild(ote, "reference").getAttribute("value").startsWith("#")) { 155// Element t = cda.getByXmlId(cda.getChild(ote, "reference").getAttribute("value").substring(1)); 156// String ot = t.getTextContent().trim(); 157// cc.setText(Utilities.noString(ot) ? null : ot); 158// } else 159// throw new Exception("external references not handled yet "+cda.getChild(ote, "reference").getAttribute("value")); 160// } else { 161 String ot = ote.getTextContent().trim(); 162 cc.setText(Utilities.noString(ot) ? null : ot); 163 //} 164 } 165 return cc; 166 } 167 168 public Coding makeCodingFromCV(Element cd) throws Exception { 169 if (cd == null || Utilities.noString(cd.getAttribute("code"))) 170 return null; 171 Coding c = new Coding(); 172 c.setCode(cd.getAttribute("code")); 173 c.setDisplay(cd.getAttribute("displayName")); 174 String r = cd.getAttribute("codeSystem"); 175 String uri = getUriForOID(r); 176 if (uri != null) 177 c.setSystem(uri); 178 else if (isGuid(r)) 179 c.setSystem("urn:uuid:" + r); 180 else if (UriForOid(r) != null) 181 c.setSystem(UriForOid(r)); 182 else 183 c.setSystem("urn:oid:" + r); 184 return c; 185 } 186 187 private String getUriForOID(String r) { 188 if (r.equals("2.16.840.1.113883.6.1")) 189 return "http://loinc.org"; 190 if (r.equals("2.16.840.1.113883.6.96")) 191 return "http://snomed.info/sct"; 192 return null; 193 } 194 195 public Address makeAddressFromAD(Element e) { 196 if (e == null) 197 return null; 198 Address a = new Address(); 199 String use = e.getAttribute("use"); 200 if (use != null) { 201 if (use.equals("H") || use.equals("HP") || use.equals("HV")) 202 a.setUse(AddressUse.HOME); 203 else if (use.equals("WP") || use.equals("DIR") || use.equals("PUB")) 204 a.setUse(AddressUse.WORK); 205 else if (use.equals("TMP")) 206 a.setUse(AddressUse.TEMP); 207 else if (use.equals("BAD")) 208 a.setUse(AddressUse.OLD); 209 } 210 Node n = e.getFirstChild(); 211 while (n != null) { 212 if (n.getNodeType() == Node.ELEMENT_NODE) { 213 String v = n.getTextContent(); 214 if (n.getLocalName().equals("additionalLocator")) 215 a.getLine().add(makeString(v)); 216// else if (e.getLocalName().equals("unitID")) 217// else if (e.getLocalName().equals("unitType")) 218 else if (n.getLocalName().equals("deliveryAddressLine")) 219 a.getLine().add(makeString(v)); 220// else if (e.getLocalName().equals("deliveryInstallationType")) 221// else if (e.getLocalName().equals("deliveryInstallationArea")) 222// else if (e.getLocalName().equals("deliveryInstallationQualifier")) 223// else if (e.getLocalName().equals("deliveryMode")) 224// else if (e.getLocalName().equals("deliveryModeIdentifier")) 225 else if (n.getLocalName().equals("streetAddressLine")) 226 a.getLine().add(makeString(v)); 227// else if (e.getLocalName().equals("houseNumber")) 228// else if (e.getLocalName().equals("buildingNumberSuffix")) 229// else if (e.getLocalName().equals("postBox")) 230// else if (e.getLocalName().equals("houseNumberNumeric")) 231// else if (e.getLocalName().equals("streetName")) 232// else if (e.getLocalName().equals("streetNameBase")) 233// else if (e.getLocalName().equals("streetNameType")) 234 else if (n.getLocalName().equals("direction")) 235 a.getLine().add(makeString(v)); 236 else if (n.getLocalName().equals("careOf")) 237 a.getLine().add(makeString(v)); 238// else if (e.getLocalName().equals("censusTract")) 239 else if (n.getLocalName().equals("country")) 240 a.setCountry(v); 241 //else if (e.getLocalName().equals("county")) 242 else if (n.getLocalName().equals("city")) 243 a.setCity(v); 244// else if (e.getLocalName().equals("delimiter")) 245// else if (e.getLocalName().equals("precinct")) 246 else if (n.getLocalName().equals("state")) 247 a.setState(v); 248 else if (n.getLocalName().equals("postalCode")) 249 a.setPostalCode(v); 250 } 251 n = n.getNextSibling(); 252 } 253 return a; 254 } 255 256 public StringType makeString(String v) { 257 StringType s = new StringType(); 258 s.setValue(v); 259 return s; 260 } 261 262 public ContactPoint makeContactFromTEL(Element e) throws Exception { 263 if (e == null) 264 return null; 265 if (e.hasAttribute("nullFlavor")) 266 return null; 267 ContactPoint c = new ContactPoint(); 268 String use = e.getAttribute("use"); 269 if (use != null) { 270 if (use.equals("H") || use.equals("HP") || use.equals("HV")) 271 c.setUse(ContactPointUse.HOME); 272 else if (use.equals("WP") || use.equals("DIR") || use.equals("PUB")) 273 c.setUse(ContactPointUse.WORK); 274 else if (use.equals("TMP")) 275 c.setUse(ContactPointUse.TEMP); 276 else if (use.equals("BAD")) 277 c.setUse(ContactPointUse.OLD); 278 } 279 if (e.getAttribute("value") != null) { 280 String[] url = e.getAttribute("value").split(":"); 281 if (url.length == 1) { 282 c.setValue(url[0].trim()); 283 c.setSystem(ContactPointSystem.PHONE); 284 } else { 285 if (url[0].equals("tel")) 286 c.setSystem(ContactPointSystem.PHONE); 287 else if (url[0].equals("mailto")) 288 c.setSystem(ContactPointSystem.EMAIL); 289 else if (e.getAttribute("value").contains(":")) 290 c.setSystem(ContactPointSystem.OTHER); 291 else 292 c.setSystem(ContactPointSystem.PHONE); 293 c.setValue(url[1].trim()); 294 } 295 } 296 return c; 297 298 } 299 300 public HumanName makeNameFromEN(Element e) { 301 if (e == null) 302 return null; 303 HumanName hn = new HumanName(); 304 String use = e.getAttribute("use"); 305 if (use != null) { 306 if (use.equals("L")) 307 hn.setUse(NameUse.USUAL); 308 else if (use.equals("C")) 309 hn.setUse(NameUse.OFFICIAL); 310 else if (use.equals("P") || use.equals("A")) 311 hn.setUse(NameUse.ANONYMOUS); 312 else if (use.equals("TMP")) 313 hn.setUse(NameUse.TEMP); 314 else if (use.equals("BAD")) 315 hn.setUse(NameUse.OLD); 316 } 317 318 Node n = e.getFirstChild(); 319 while (n != null) { 320 if (n.getNodeType() == Node.ELEMENT_NODE) { 321 String v = n.getTextContent(); 322 if (n.getLocalName().equals("family")) 323 hn.setFamilyElement(makeString(v)); 324 else if (n.getLocalName().equals("given")) 325 hn.getGiven().add(makeString(v)); 326 else if (n.getLocalName().equals("prefix")) 327 hn.getPrefix().add(makeString(v)); 328 else if (n.getLocalName().equals("suffix")) 329 hn.getSuffix().add(makeString(v)); 330 } 331 n = n.getNextSibling(); 332 } 333 return hn; 334 } 335 336 public DateTimeType makeDateTimeFromTS(Element ts) throws Exception { 337 if (ts == null) 338 return null; 339 340 String v = ts.getAttribute("value"); 341 if (Utilities.noString(v)) 342 return null; 343 344 if (v.length() > 8 && !hasTimezone(v)) 345 v += defaultTimezone; 346 DateTimeType d = DateTimeType.parseV3(v); 347 return d; 348 } 349 350 private boolean hasTimezone(String v) { 351 return v.contains("+") || v.contains("-") || v.endsWith("Z"); 352 } 353 354 355 public DateType makeDateFromTS(Element ts) throws Exception { 356 if (ts == null) 357 return null; 358 359 String v = ts.getAttribute("value"); 360 if (Utilities.noString(v)) 361 return null; 362 DateType d = DateType.parseV3(v); 363 return d; 364 } 365 366 public Period makePeriodFromIVL(Element ivl) throws Exception { 367 if (ivl == null) 368 return null; 369 Period p = new Period(); 370 Element low = cda.getChild(ivl, "low"); 371 if (low != null) 372 p.setStartElement(makeDateTimeFromTS(low)); 373 Element high = cda.getChild(ivl, "high"); 374 if (high != null) 375 p.setEndElement(makeDateTimeFromTS(high)); 376 377 if (p.getStartElement() != null || p.getEndElement() != null) 378 return p; 379 else 380 return null; 381 } 382 383 // this is a weird one - where CDA has an IVL, and FHIR has a date 384 public DateTimeType makeDateTimeFromIVL(Element ivl) throws Exception { 385 if (ivl == null) 386 return null; 387 if (ivl.hasAttribute("value")) 388 return makeDateTimeFromTS(ivl); 389 Element high = cda.getChild(ivl, "high"); 390 if (high != null) 391 return makeDateTimeFromTS(high); 392 Element low = cda.getChild(ivl, "low"); 393 if (low != null) 394 return makeDateTimeFromTS(low); 395 return null; 396 } 397 398 public Type makeStringFromED(Element e) throws Exception { 399 if (e == null) 400 return null; 401 if (cda.getChild(e, "reference") != null) { 402 if (cda.getChild(e, "reference").getAttribute("value").startsWith("#")) { 403 Element t = cda.getByXmlId(cda.getChild(e, "reference").getAttribute("value").substring(1)); 404 String ot = t.getTextContent().trim(); 405 return Utilities.noString(ot) ? null : Factory.newString_(ot); 406 } else 407 throw new Exception("external references not handled yet " + cda.getChild(e, "reference").getAttribute("value")); 408 } 409 return Factory.newString_(e.getTextContent()); 410 } 411 412 public Type makeTypeFromANY(Element e) throws Exception { 413 if (e == null) 414 return null; 415 String t = e.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "type"); 416 if (Utilities.noString(t)) 417 throw new Exception("Missing type on RIM attribute with type any"); 418 if (t.equals("CD") || t.equals("CE")) 419 return makeCodeableConceptFromCD(e); 420 else if (t.equals("ST")) 421 return makeStringFromED(e); 422 else 423 throw new Exception("Not done yet (type = " + t + ")"); 424 } 425 426 public Type makeMatchingTypeFromIVL(Element ivl) throws Exception { 427 if (ivl == null) 428 return null; 429 if (ivl.getAttribute("value") != null) 430 return makeDateTimeFromIVL(ivl); 431 if (cda.getChild(ivl, "low") != null || cda.getChild(ivl, "high") != null) 432 return makePeriodFromIVL(ivl); 433 throw new Exception("not handled yet"); 434 } 435 436 public Type makeCodeableConceptFromNullFlavor(String nf) throws Exception { 437 // Some nullFlavors have explicit values in value sets. This can only be called where there aren't. 438 if (nf == null || "".equals(nf)) 439 return null; 440 if ("NI".equals(nf)) 441 return null; // there's no code for this 442 if ("NA".equals(nf)) 443 return Factory.newCodeableConcept("unsupported", "http://hl7.org/fhir/data-absent-reason", "Unsupported"); // todo: is this reasonable? Why else would you use N/A? 444 if ("UNK".equals(nf)) 445 return Factory.newCodeableConcept("unknown", "http://hl7.org/fhir/data-absent-reason", "Unknown"); 446 if ("ASKU".equals(nf)) 447 return Factory.newCodeableConcept("asked", "http://hl7.org/fhir/data-absent-reason", "Asked/Unknown"); 448 if ("NAV".equals(nf)) 449 return Factory.newCodeableConcept("temp", "http://hl7.org/fhir/data-absent-reason", "Temporarily Unavailable"); 450 if ("NASK".equals(nf)) 451 return Factory.newCodeableConcept("notasked", "http://hl7.org/fhir/data-absent-reason", "Not Asked"); 452 if ("MSK".equals(nf)) 453 return Factory.newCodeableConcept("masked", "http://hl7.org/fhir/data-absent-reason", "Masked"); 454 if ("OTH".equals(nf)) 455 return null; // well, what should be done? 456 return null; // well, what should be done? 457 458 } 459 460 public Range makeRangeFromIVLPQ(Element ivlpq) throws Exception { 461 if (ivlpq == null) 462 return null; 463 Element low = cda.getChild(ivlpq, "low"); 464 Element high = cda.getChild(ivlpq, "high"); 465 if (low == null && high == null) 466 return null; 467 Range r = new Range(); 468 r.setLow(makeSimpleQuantityFromPQ(low, ivlpq.getAttribute("unit"))); 469 r.setHigh(makeSimpleQuantityFromPQ(high, ivlpq.getAttribute("unit"))); 470 return r; 471 } 472 473 public Quantity makeQuantityFromPQ(Element pq) throws Exception { 474 return makeQuantityFromPQ(pq, null); 475 } 476 477 public Quantity makeQuantityFromPQ(Element pq, String units) throws Exception { 478 if (pq == null) 479 return null; 480 Quantity qty = new Quantity(); 481 String n = pq.getAttribute("value").replace(",", "").trim(); 482 try { 483 qty.setValue(new BigDecimal(n)); 484 } catch (Exception e) { 485 throw new Exception("Unable to process value '" + n + "'", e); 486 } 487 units = Utilities.noString(pq.getAttribute("unit")) ? units : pq.getAttribute("unit"); 488 if (!Utilities.noString(units)) { 489 if (ucumSvc == null || ucumSvc.validate(units) != null) 490 qty.setUnit(units); 491 else { 492 qty.setCode(units); 493 qty.setSystem("http://unitsofmeasure.org"); 494 qty.setUnit(ucumSvc.getCommonDisplay(units)); 495 } 496 } 497 return qty; 498 } 499 500 public SimpleQuantity makeSimpleQuantityFromPQ(Element pq, String units) throws Exception { 501 if (pq == null) 502 return null; 503 SimpleQuantity qty = new SimpleQuantity(); 504 String n = pq.getAttribute("value").replace(",", "").trim(); 505 try { 506 qty.setValue(new BigDecimal(n)); 507 } catch (Exception e) { 508 throw new Exception("Unable to process value '" + n + "'", e); 509 } 510 units = Utilities.noString(pq.getAttribute("unit")) ? units : pq.getAttribute("unit"); 511 if (!Utilities.noString(units)) { 512 if (ucumSvc == null || ucumSvc.validate(units) != null) 513 qty.setUnit(units); 514 else { 515 qty.setCode(units); 516 qty.setSystem("http://unitsofmeasure.org"); 517 qty.setUnit(ucumSvc.getCommonDisplay(units)); 518 } 519 } 520 return qty; 521 } 522 523 public AdministrativeGender makeGenderFromCD(Element cd) throws Exception { 524 String code = cd.getAttribute("code"); 525 String system = cd.getAttribute("codeSystem"); 526 if ("2.16.840.1.113883.5.1".equals(system)) { 527 if ("F".equals(code)) 528 return AdministrativeGender.FEMALE; 529 if ("M".equals(code)) 530 return AdministrativeGender.MALE; 531 } 532 throw new Exception("Unable to read Gender " + system + "::" + code); 533 } 534 535 /* 536 /entry[COMP]/substanceAdministration[SBADM,EVN]/effectiveTime[type:EIVL_TS]: 389 537 /entry[COMP]/substanceAdministration[SBADM,EVN]/effectiveTime[type:EIVL_TS]/event: 389 538 /entry[COMP]/substanceAdministration[SBADM,EVN]/effectiveTime[type:IVL_TS]: 33470 539 /entry[COMP]/substanceAdministration[SBADM,EVN]/effectiveTime[type:IVL_TS]/high: 20566 540 /entry[COMP]/substanceAdministration[SBADM,EVN]/effectiveTime[type:IVL_TS]/high[nullFlavor:NA]: 9581 541 /entry[COMP]/substanceAdministration[SBADM,EVN]/effectiveTime[type:IVL_TS]/low: 32501 542 /entry[COMP]/substanceAdministration[SBADM,EVN]/effectiveTime[type:IVL_TS]/low[nullFlavor:UNK]: 969 543 /entry[COMP]/substanceAdministration[SBADM,EVN]/effectiveTime[type:PIVL_TS]: 17911 544 /entry[COMP]/substanceAdministration[SBADM,EVN]/effectiveTime[type:PIVL_TS]/period: 17911 545 */ 546 public Type makeSomethingFromGTS(List<Element> children) throws Exception { 547 if (children.isEmpty()) 548 return null; 549 if (children.size() == 1) { 550 String type = children.get(0).getAttribute("xsi:type"); 551 if (type.equals("IVL_TS")) 552 return makePeriodFromIVL(children.get(0)); 553 else 554 throw new Exception("Unknown GTS type '" + type + "'"); 555 } 556 CommaSeparatedStringBuilder t = new CommaSeparatedStringBuilder(); 557 for (Element c : children) 558 t.append(c.getAttribute("xsi:type")); 559 if (t.toString().equals("IVL_TS, PIVL_TS")) 560 return makeTimingFromBoundedPIVL(children.get(0), children.get(1)); 561 if (t.toString().equals("IVL_TS, EIVL_TS")) 562 return makeTimingFromBoundedEIVL(children.get(0), children.get(1)); 563 throw new Exception("Unknown GTS pattern '" + t + "'"); 564 } 565 566 private Type makeTimingFromBoundedEIVL(Element ivl, Element eivl) throws Exception { 567 Timing t = new Timing(); 568 t.setRepeat(new TimingRepeatComponent()); 569 Element e = cda.getChild(eivl, "event"); 570 t.getRepeat().setBounds(makePeriodFromIVL(ivl)); 571 t.getRepeat().addWhen(convertEventTiming(e.getAttribute("code"))); 572 return t; 573 } 574 575 private EventTiming convertEventTiming(String e) throws Exception { 576 if ("HS".equals(e)) 577 return EventTiming.HS; 578 throw new Exception("Unknown event " + e); 579 } 580 581 private Timing makeTimingFromBoundedPIVL(Element ivl, Element pivl) throws Exception { 582 Timing t = new Timing(); 583 t.setRepeat(new TimingRepeatComponent()); 584 Element p = cda.getChild(pivl, "period"); 585 t.getRepeat().setBounds(makePeriodFromIVL(ivl)); 586 t.getRepeat().setPeriod(new BigDecimal(p.getAttribute("value"))); 587 t.getRepeat().setPeriodUnit(convertTimeUnit(p.getAttribute("unit"))); 588 return t; 589 } 590 591 private UnitsOfTime convertTimeUnit(String u) throws Exception { 592 if ("h".equals(u)) 593 return UnitsOfTime.H; 594 if ("d".equals(u)) 595 return UnitsOfTime.D; 596 if ("w".equals(u)) 597 return UnitsOfTime.WK; 598 throw new Exception("Unknown unit of time " + u); 599 } 600 601 public Set<String> getOids() { 602 return oids; 603 } 604 605 public boolean isGenerateMissingExtensions() { 606 return generateMissingExtensions; 607 } 608 609 public void setGenerateMissingExtensions(boolean generateMissingExtensions) { 610 this.generateMissingExtensions = generateMissingExtensions; 611 } 612 613 614}