
001package org.hl7.fhir.r4.elementmodel; 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 032import java.util.ArrayList; 033import java.util.Collections; 034import java.util.Comparator; 035import java.util.HashMap; 036import java.util.HashSet; 037import java.util.List; 038import java.util.Map; 039import java.util.Set; 040 041import org.apache.commons.lang3.Validate; 042import org.hl7.fhir.exceptions.FHIRException; 043import org.hl7.fhir.r4.conformance.ProfileUtilities; 044import org.hl7.fhir.r4.model.Base; 045import org.hl7.fhir.r4.model.ElementDefinition; 046import org.hl7.fhir.r4.model.ElementDefinition.TypeRefComponent; 047import org.hl7.fhir.r4.model.Enumerations.BindingStrength; 048import org.hl7.fhir.r4.model.ICoding; 049import org.hl7.fhir.r4.model.StringType; 050import org.hl7.fhir.r4.model.StructureDefinition; 051import org.hl7.fhir.r4.model.Type; 052import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent; 053import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome; 054import org.hl7.fhir.utilities.ElementDecoration; 055import org.hl7.fhir.utilities.ElementDecoration.DecorationType; 056import org.hl7.fhir.utilities.Utilities; 057import org.hl7.fhir.utilities.xhtml.XhtmlNode; 058 059/** 060 * This class represents the underlying reference model of FHIR 061 * 062 * A resource is nothing but a set of elements, where every element has a name, 063 * maybe a stated type, maybe an id, and either a value or child elements (one 064 * or the other, but not both or neither) 065 * 066 * @author Grahame Grieve 067 * 068 */ 069@Deprecated 070public class Element extends Base { 071 072 public enum SpecialElement { 073 CONTAINED, BUNDLE_ENTRY, BUNDLE_OUTCOME, PARAMETER; 074 075 public static SpecialElement fromProperty(Property property) { 076 if (property.getStructure().getIdElement().getIdPart().equals("Parameters")) 077 return PARAMETER; 078 if (property.getStructure().getIdElement().getIdPart().equals("Bundle") && property.getName().equals("resource")) 079 return BUNDLE_ENTRY; 080 if (property.getStructure().getIdElement().getIdPart().equals("Bundle") && property.getName().equals("outcome")) 081 return BUNDLE_OUTCOME; 082 if (property.getName().equals("contained")) 083 return CONTAINED; 084 throw new Error("Unknown resource containing a native resource: " + property.getDefinition().getId()); 085 } 086 } 087 088 private List<String> comments;// not relevant for production, but useful in documentation 089 private String name; 090 private String type; 091 private String value; 092 private int index = -1; 093 private List<Element> children; 094 private Property property; 095 private Property elementProperty; // this is used when special is set to true - it tracks the underlying element 096 // property which is used in a few places 097 private int line; 098 private int col; 099 private SpecialElement special; 100 private XhtmlNode xhtml; // if this is populated, then value will also hold the string representation 101 private String explicitType; // for xsi:type attribute 102 103 public Element(String name) { 104 super(); 105 this.name = name; 106 } 107 108 public Element(Element other) { 109 super(); 110 name = other.name; 111 type = other.type; 112 property = other.property; 113 elementProperty = other.elementProperty; 114 special = other.special; 115 } 116 117 public Element(String name, Property property) { 118 super(); 119 this.name = name; 120 this.property = property; 121 } 122 123 public Element(String name, Property property, String type, String value) { 124 super(); 125 this.name = name; 126 this.property = property; 127 this.type = type; 128 this.value = value; 129 } 130 131 public void updateProperty(Property property, SpecialElement special, Property elementProperty) { 132 this.property = property; 133 this.elementProperty = elementProperty; 134 this.special = special; 135 } 136 137 public SpecialElement getSpecial() { 138 return special; 139 } 140 141 public String getName() { 142 return name; 143 } 144 145 public String getType() { 146 if (type == null) 147 return property.getType(name); 148 else 149 return type; 150 } 151 152 public String getValue() { 153 return value; 154 } 155 156 public boolean hasChildren() { 157 return !(children == null || children.isEmpty()); 158 } 159 160 public List<Element> getChildren() { 161 if (children == null) 162 children = new ArrayList<Element>(); 163 return children; 164 } 165 166 public boolean hasComments() { 167 return !(comments == null || comments.isEmpty()); 168 } 169 170 public List<String> getComments() { 171 if (comments == null) 172 comments = new ArrayList<String>(); 173 return comments; 174 } 175 176 public Property getProperty() { 177 return property; 178 } 179 180 public void setValue(String value) { 181 this.value = value; 182 } 183 184 public void setType(String type) { 185 this.type = type; 186 187 } 188 189 public boolean hasValue() { 190 return value != null; 191 } 192 193 public List<Element> getChildrenByName(String name) { 194 List<Element> res = new ArrayList<Element>(); 195 if (hasChildren()) { 196 for (Element child : children) 197 if (name.equals(child.getName())) 198 res.add(child); 199 } 200 return res; 201 } 202 203 public void numberChildren() { 204 if (children == null) 205 return; 206 207 String last = ""; 208 int index = 0; 209 for (Element child : children) { 210 if (child.getProperty().isList()) { 211 if (last.equals(child.getName())) { 212 index++; 213 } else { 214 last = child.getName(); 215 index = 0; 216 } 217 child.index = index; 218 } else { 219 child.index = -1; 220 } 221 child.numberChildren(); 222 } 223 } 224 225 public int getIndex() { 226 return index; 227 } 228 229 public boolean hasIndex() { 230 return index > -1; 231 } 232 233 public void setIndex(int index) { 234 this.index = index; 235 } 236 237 public String getChildValue(String name) { 238 if (children == null) 239 return null; 240 for (Element child : children) { 241 if (name.equals(child.getName())) 242 return child.getValue(); 243 } 244 return null; 245 } 246 247 public void setChildValue(String name, String value) { 248 if (children == null) 249 children = new ArrayList<Element>(); 250 for (Element child : children) { 251 if (name.equals(child.getName())) { 252 if (!child.isPrimitive()) 253 throw new Error("Cannot set a value of a non-primitive type (" + name + " on " + this.getName() + ")"); 254 child.setValue(value); 255 } 256 } 257 try { 258 setProperty(name.hashCode(), name, new StringType(value)); 259 } catch (FHIRException e) { 260 throw new Error(e); 261 } 262 } 263 264 public List<Element> getChildren(String name) { 265 List<Element> res = new ArrayList<Element>(); 266 if (children != null) 267 for (Element child : children) { 268 if (name.equals(child.getName())) 269 res.add(child); 270 } 271 return res; 272 } 273 274 public boolean hasType() { 275 if (type == null) 276 return property.hasType(name); 277 else 278 return true; 279 } 280 281 @Override 282 public String fhirType() { 283 return getType(); 284 } 285 286 @Override 287 public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException { 288 if (isPrimitive() && (hash == "value".hashCode()) && !Utilities.noString(value)) { 289// String tn = getType(); 290// throw new Error(tn+" not done yet"); 291 Base[] b = new Base[1]; 292 b[0] = new StringType(value); 293 return b; 294 } 295 296 List<Base> result = new ArrayList<Base>(); 297 if (children != null) { 298 for (Element child : children) { 299 if (child.getName().equals(name)) 300 result.add(child); 301 if (child.getName().startsWith(name) && child.getProperty().isChoice() 302 && child.getProperty().getName().equals(name + "[x]")) 303 result.add(child); 304 } 305 } 306 if (result.isEmpty() && checkValid) { 307// throw new FHIRException("not determined yet"); 308 } 309 return result.toArray(new Base[result.size()]); 310 } 311 312 @Override 313 protected void listChildren(List<org.hl7.fhir.r4.model.Property> childProps) { 314 if (children != null) { 315 Map<String, org.hl7.fhir.r4.model.Property> map = new HashMap<String, org.hl7.fhir.r4.model.Property>(); 316 for (Element c : children) { 317 org.hl7.fhir.r4.model.Property p = map.get(c.getName()); 318 if (p == null) { 319 p = new org.hl7.fhir.r4.model.Property(c.getName(), c.fhirType(), 320 c.getProperty().getDefinition().getDefinition(), c.getProperty().getDefinition().getMin(), 321 maxToInt(c.getProperty().getDefinition().getMax()), c); 322 childProps.add(p); 323 map.put(c.getName(), p); 324 325 } else 326 p.getValues().add(c); 327 } 328 } 329 } 330 331 @Override 332 public Base copy() { 333 Element element = new Element(this); 334 this.copyValues(element); 335 return element; 336 } 337 338 @Override 339 public void copyValues(Base dst) { 340 super.copyValues(dst); 341 342 Element dest = (Element) dst; 343 if (comments != null) { 344 dest.comments = new ArrayList<>(); 345 dest.comments.addAll(comments); 346 } else { 347 dest.comments = null; 348 } 349 dest.value = value; 350 if (children != null) { 351 dest.children = new ArrayList<>(); 352 for (Element child : children) { 353 dest.children.add((Element) child.copy()); 354 } 355 } else { 356 dest.children = null; 357 } 358 dest.line = line; 359 dest.col = col; 360 dest.xhtml = xhtml; 361 dest.explicitType = explicitType; 362 } 363 364 @Override 365 public Base setProperty(int hash, String name, Base value) throws FHIRException { 366 if ("xhtml".equals(getType()) && (hash == "value".hashCode())) { 367 this.xhtml = castToXhtml(value); 368 this.value = castToXhtmlString(value); 369 return this; 370 } 371 if (isPrimitive() && (hash == "value".hashCode())) { 372 this.value = castToString(value).asStringValue(); 373 return this; 374 } 375 376 if (!value.isPrimitive() && !(value instanceof Element)) { 377 if (isDataType(value)) 378 value = convertToElement(property.getChild(name), value); 379 else 380 throw new FHIRException("Cannot set property " + name + " on " + this.name 381 + " - value is not a primitive type (" + value.fhirType() + ") or an ElementModel type"); 382 } 383 384 if (children == null) 385 children = new ArrayList<Element>(); 386 Element childForValue = null; 387 388 // look through existing children 389 for (Element child : children) { 390 if (child.getName().equals(name)) { 391 if (!child.isList()) { 392 childForValue = child; 393 break; 394 } else { 395 Element ne = new Element(child); 396 children.add(ne); 397 numberChildren(); 398 childForValue = ne; 399 break; 400 } 401 } 402 } 403 404 int i = 0; 405 if (childForValue == null) 406 for (Property p : property.getChildProperties(this.name, type)) { 407 int t = -1; 408 for (int c = 0; c < children.size(); c++) { 409 Element e = children.get(c); 410 if (p.getName().equals(e.getName())) 411 t = c; 412 } 413 if (t > i) 414 i = t; 415 if (p.getName().equals(name) || p.getName().equals(name + "[x]")) { 416 Element ne = new Element(name, p); 417 children.add(i, ne); 418 childForValue = ne; 419 break; 420 } 421 } 422 423 if (childForValue == null) 424 throw new Error("Cannot set property " + name + " on " + this.name); 425 else if (value.isPrimitive()) { 426 if (childForValue.property.getName().endsWith("[x]")) 427 childForValue.name = name + Utilities.capitalize(value.fhirType()); 428 childForValue.setValue(value.primitiveValue()); 429 } else { 430 Element ve = (Element) value; 431 childForValue.type = ve.getType(); 432 if (childForValue.property.getName().endsWith("[x]")) 433 childForValue.name = name + Utilities.capitalize(childForValue.type); 434 else if (value.isResource()) { 435 if (childForValue.elementProperty == null) 436 childForValue.elementProperty = childForValue.property; 437 childForValue.property = ve.property; 438 childForValue.special = SpecialElement.BUNDLE_ENTRY; 439 } 440 if (ve.children != null) { 441 if (childForValue.children == null) 442 childForValue.children = new ArrayList<Element>(); 443 else 444 childForValue.children.clear(); 445 childForValue.children.addAll(ve.children); 446 } 447 } 448 return childForValue; 449 } 450 451 private Base convertToElement(Property prop, Base v) throws FHIRException { 452 return new ObjectConverter(property.getContext()).convert(prop, (Type) v); 453 } 454 455 private boolean isDataType(Base v) { 456 return v instanceof Type && property.getContext().getTypeNames().contains(v.fhirType()); 457 } 458 459 @Override 460 public Base makeProperty(int hash, String name) throws FHIRException { 461 if (isPrimitive() && (hash == "value".hashCode())) { 462 return new StringType(value); 463 } 464 465 if (children == null) 466 children = new ArrayList<Element>(); 467 468 // look through existing children 469 for (Element child : children) { 470 if (child.getName().equals(name)) { 471 if (!child.isList()) { 472 return child; 473 } else { 474 Element ne = new Element(child); 475 children.add(ne); 476 numberChildren(); 477 return ne; 478 } 479 } 480 } 481 482 for (Property p : property.getChildProperties(this.name, type)) { 483 if (p.getName().equals(name)) { 484 Element ne = new Element(name, p); 485 children.add(ne); 486 return ne; 487 } 488 } 489 490 throw new Error("Unrecognised name " + name + " on " + this.name); 491 } 492 493 private int maxToInt(String max) { 494 if (max.equals("*")) 495 return Integer.MAX_VALUE; 496 else 497 return Integer.parseInt(max); 498 } 499 500 @Override 501 public boolean isPrimitive() { 502 return type != null ? property.isPrimitive(type) : property.isPrimitive(property.getType(name)); 503 } 504 505 @Override 506 public boolean isBooleanPrimitive() { 507 return isPrimitive() && ("boolean".equals(type) || "boolean".equals(property.getType(name))); 508 } 509 510 @Override 511 public boolean isResource() { 512 return property.isResource(); 513 } 514 515 @Override 516 public boolean hasPrimitiveValue() { 517 return property.isPrimitiveName(name) || property.IsLogicalAndHasPrimitiveValue(name); 518 } 519 520 @Override 521 public String primitiveValue() { 522 if (isPrimitive()) 523 return value; 524 else { 525 if (hasPrimitiveValue() && children != null) { 526 for (Element c : children) { 527 if (c.getName().equals("value")) 528 return c.primitiveValue(); 529 } 530 } 531 return null; 532 } 533 } 534 535 // for the validator 536 public int line() { 537 return line; 538 } 539 540 public int col() { 541 return col; 542 } 543 544 public Element markLocation(int line, int col) { 545 this.line = line; 546 this.col = col; 547 return this; 548 } 549 550 public void clearDecorations() { 551 clearUserData("fhir.decorations"); 552 for (Element e : children) 553 e.clearDecorations(); 554 } 555 556 public void markValidation(StructureDefinition profile, ElementDefinition definition) { 557 @SuppressWarnings("unchecked") 558 List<ElementDecoration> decorations = (List<ElementDecoration>) getUserData("fhir.decorations"); 559 if (decorations == null) { 560 decorations = new ArrayList<>(); 561 setUserData("fhir.decorations", decorations); 562 } 563 decorations.add(new ElementDecoration(DecorationType.TYPE, profile.getUserString("path"), definition.getPath())); 564 if (definition.getId() != null && tail(definition.getId()).contains(":")) { 565 String[] details = tail(definition.getId()).split(":"); 566 decorations.add(new ElementDecoration(DecorationType.SLICE, null, details[1])); 567 } 568 } 569 570 private String tail(String id) { 571 return id.contains(".") ? id.substring(id.lastIndexOf(".") + 1) : id; 572 } 573 574 public Element getNamedChild(String name) { 575 if (children == null) 576 return null; 577 Element result = null; 578 for (Element child : children) { 579 if (child.getName().equals(name)) { 580 if (result == null) 581 result = child; 582 else 583 throw new Error("Attempt to read a single element when there is more than one present (" + name + ")"); 584 } 585 } 586 return result; 587 } 588 589 public void getNamedChildren(String name, List<Element> list) { 590 if (children != null) 591 for (Element child : children) 592 if (child.getName().equals(name)) 593 list.add(child); 594 } 595 596 public String getNamedChildValue(String name) { 597 Element child = getNamedChild(name); 598 return child == null ? null : child.value; 599 } 600 601 public void getNamedChildrenWithWildcard(String string, List<Element> values) { 602 Validate.isTrue(string.endsWith("[x]")); 603 604 String start = string.substring(0, string.length() - 3); 605 if (children != null) { 606 for (Element child : children) { 607 if (child.getName().startsWith(start)) { 608 values.add(child); 609 } 610 } 611 } 612 } 613 614 public XhtmlNode getXhtml() { 615 return xhtml; 616 } 617 618 public Element setXhtml(XhtmlNode xhtml) { 619 this.xhtml = xhtml; 620 return this; 621 } 622 623 @Override 624 public boolean isEmpty() { 625 // GG: this used to also test !"".equals(value). 626 // the condition where "" is empty and there are no children is an error, and so 627 // this really only manifested as an issue in corner cases technical testing of 628 // the validator / FHIRPath. 629 // it should not cause any problems in real life. 630 if (value != null) { 631 return false; 632 } 633 for (Element next : getChildren()) { 634 if (!next.isEmpty()) { 635 return false; 636 } 637 } 638 return true; 639 } 640 641 public Property getElementProperty() { 642 return elementProperty; 643 } 644 645 public boolean hasElementProperty() { 646 return elementProperty != null; 647 } 648 649 public boolean hasChild(String name) { 650 return getNamedChild(name) != null; 651 } 652 653 public boolean hasChildren(String name) { 654 if (children != null) 655 for (Element child : children) 656 if (child.getName().equals(name)) 657 return true; 658 return false; 659 } 660 661 @Override 662 public String toString() { 663 return name + "=" + fhirType() + "[" 664 + (children == null || hasValue() ? value : Integer.toString(children.size()) + " children") + "]"; 665 } 666 667 @Override 668 public String getIdBase() { 669 return getChildValue("id"); 670 } 671 672 @Override 673 public void setIdBase(String value) { 674 setChildValue("id", value); 675 } 676 677 @Override 678 public boolean equalsDeep(Base other) { 679 if (!super.equalsDeep(other)) 680 return false; 681 if (isPrimitive() && other.isPrimitive()) 682 return primitiveValue().equals(other.primitiveValue()); 683 if (isPrimitive() || other.isPrimitive()) 684 return false; 685 Set<String> processed = new HashSet<String>(); 686 for (org.hl7.fhir.r4.model.Property p : children()) { 687 String name = p.getName(); 688 processed.add(name); 689 org.hl7.fhir.r4.model.Property o = other.getChildByName(name); 690 if (!equalsDeep(p, o)) 691 return false; 692 } 693 for (org.hl7.fhir.r4.model.Property p : children()) { 694 String name = p.getName(); 695 if (!processed.contains(name)) { 696 org.hl7.fhir.r4.model.Property o = other.getChildByName(name); 697 if (!equalsDeep(p, o)) 698 return false; 699 } 700 } 701 return true; 702 } 703 704 private boolean equalsDeep(org.hl7.fhir.r4.model.Property p, org.hl7.fhir.r4.model.Property o) { 705 if (o == null || p == null) 706 return false; 707 if (p.getValues().size() != o.getValues().size()) 708 return false; 709 for (int i = 0; i < p.getValues().size(); i++) 710 if (!Base.compareDeep(p.getValues().get(i), o.getValues().get(i), true)) 711 return false; 712 return true; 713 } 714 715 @Override 716 public boolean equalsShallow(Base other) { 717 if (!super.equalsShallow(other)) 718 return false; 719 if (isPrimitive() && other.isPrimitive()) 720 return primitiveValue().equals(other.primitiveValue()); 721 if (isPrimitive() || other.isPrimitive()) 722 return false; 723 return true; // ? 724 } 725 726 public Type asType() throws FHIRException { 727 return new ObjectConverter(property.getContext()).convertToType(this); 728 } 729 730 @Override 731 public boolean isMetadataBased() { 732 return true; 733 } 734 735 public boolean isList() { 736 if (elementProperty != null) 737 return elementProperty.isList(); 738 else 739 return property.isList(); 740 } 741 742 @Override 743 public String[] getTypesForProperty(int hash, String name) throws FHIRException { 744 Property p = property.getChildSimpleName(this.name, name); 745 if (p != null) { 746 Set<String> types = new HashSet<String>(); 747 for (TypeRefComponent tr : p.getDefinition().getType()) { 748 types.add(tr.getCode()); 749 } 750 return types.toArray(new String[] {}); 751 } 752 return super.getTypesForProperty(hash, name); 753 754 } 755 756 public void sort() { 757 if (children != null) { 758 List<Element> remove = new ArrayList<Element>(); 759 for (Element child : children) { 760 child.sort(); 761 if (child.isEmpty()) 762 remove.add(child); 763 } 764 children.removeAll(remove); 765 Collections.sort(children, new ElementSortComparator(this, this.property)); 766 } 767 } 768 769 public class ElementSortComparator implements Comparator<Element> { 770 private List<ElementDefinition> children; 771 772 public ElementSortComparator(Element e, Property property) { 773 String tn = e.getType(); 774 StructureDefinition sd = property.getContext().fetchResource(StructureDefinition.class, 775 ProfileUtilities.sdNs(tn, property.getContext().getOverrideVersionNs())); 776 if (sd != null && !sd.getAbstract()) 777 children = sd.getSnapshot().getElement(); 778 else 779 children = property.getStructure().getSnapshot().getElement(); 780 } 781 782 @Override 783 public int compare(Element e0, Element e1) { 784 int i0 = find(e0); 785 int i1 = find(e1); 786 return Integer.compare(i0, i1); 787 } 788 789 private int find(Element e0) { 790 int i = e0.elementProperty != null ? children.indexOf(e0.elementProperty.getDefinition()) 791 : children.indexOf(e0.property.getDefinition()); 792 return i; 793 } 794 795 } 796 797 public class ICodingImpl implements ICoding { 798 private String system; 799 private String version; 800 private String code; 801 private String display; 802 private boolean doesSystem; 803 private boolean doesVersion; 804 private boolean doesCode; 805 private boolean doesDisplay; 806 807 public ICodingImpl(boolean doesCode, boolean doesSystem, boolean doesVersion, boolean doesDisplay) { 808 super(); 809 this.doesCode = doesCode; 810 this.doesSystem = doesSystem; 811 this.doesVersion = doesVersion; 812 this.doesDisplay = doesDisplay; 813 } 814 815 public String getSystem() { 816 return system; 817 } 818 819 public String getVersion() { 820 return version; 821 } 822 823 public String getCode() { 824 return code; 825 } 826 827 public String getDisplay() { 828 return display; 829 } 830 831 public boolean hasSystem() { 832 return !Utilities.noString(system); 833 } 834 835 public boolean hasVersion() { 836 return !Utilities.noString(version); 837 } 838 839 public boolean hasCode() { 840 return !Utilities.noString(code); 841 } 842 843 public boolean hasDisplay() { 844 return !Utilities.noString(display); 845 } 846 847 public boolean supportsSystem() { 848 return doesSystem; 849 } 850 851 public boolean supportsVersion() { 852 return doesVersion; 853 } 854 855 public boolean supportsCode() { 856 return doesCode; 857 } 858 859 public boolean supportsDisplay() { 860 return doesDisplay; 861 } 862 } 863 864 public ICoding getAsICoding() throws FHIRException { 865 if ("code".equals(fhirType())) { 866 if (property.getDefinition().getBinding().getStrength() != BindingStrength.REQUIRED) 867 return null; 868 ICodingImpl c = new ICodingImpl(true, true, false, false); 869 c.code = primitiveValue(); 870 ValueSetExpansionOutcome vse = property.getContext().expandVS(property.getDefinition().getBinding(), true, false); 871 if (vse.getValueset() == null) 872 return null; 873 for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) { 874 if (cc.getCode().equals(c.code)) { 875 c.system = cc.getSystem(); 876 if (cc.hasVersion()) { 877 c.doesVersion = true; 878 c.version = cc.getVersion(); 879 } 880 if (cc.hasDisplay()) { 881 c.doesDisplay = true; 882 c.display = cc.getDisplay(); 883 } 884 } 885 } 886 if (c.system == null) 887 return null; 888 return c; 889 } else if ("Coding".equals(fhirType())) { 890 ICodingImpl c = new ICodingImpl(true, true, true, true); 891 c.system = getNamedChildValue("system"); 892 c.code = getNamedChildValue("code"); 893 c.display = getNamedChildValue("display"); 894 c.version = getNamedChildValue("version"); 895 return c; 896 } else if ("Quantity".equals(fhirType())) { 897 ICodingImpl c = new ICodingImpl(true, true, false, false); 898 c.system = getNamedChildValue("system"); 899 c.code = getNamedChildValue("code"); 900 return c; 901 } else 902 return null; 903 } 904 905 public String getExplicitType() { 906 return explicitType; 907 } 908 909 public void setExplicitType(String explicitType) { 910 this.explicitType = explicitType; 911 } 912 913}