
001package org.hl7.fhir.dstu3.utils; 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 033 034import java.util.List; 035 036import org.hl7.fhir.dstu3.model.BooleanType; 037import org.hl7.fhir.dstu3.model.CodeSystem; 038import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent; 039import org.hl7.fhir.dstu3.model.CodeSystem.ConceptPropertyComponent; 040import org.hl7.fhir.dstu3.model.CodeSystem.PropertyComponent; 041import org.hl7.fhir.dstu3.model.CodeSystem.PropertyType; 042import org.hl7.fhir.dstu3.model.DateTimeType; 043import org.hl7.fhir.dstu3.model.Identifier; 044import org.hl7.fhir.dstu3.model.Meta; 045import org.hl7.fhir.dstu3.model.UriType; 046import org.hl7.fhir.exceptions.FHIRException; 047import org.hl7.fhir.exceptions.FHIRFormatError; 048import org.hl7.fhir.utilities.Utilities; 049 050public class CodeSystemUtilities { 051 052 public static boolean isDeprecated(CodeSystem cs, ConceptDefinitionComponent def) { 053 for (ConceptPropertyComponent p : def.getProperty()) { 054 if (p.getCode().equals("deprecated") && p.hasValue() && p.getValue() instanceof BooleanType) 055 return ((BooleanType) p.getValue()).getValue(); 056 if (p.getCode().equals("deprecationDate") && p.hasValue() && p.getValue() instanceof DateTimeType) 057 return ((DateTimeType) p.getValue()).before(new DateTimeType()); 058 } 059 return false; 060 } 061 062 public static boolean isNotSelectable(CodeSystem cs, ConceptDefinitionComponent def) { 063 for (ConceptPropertyComponent p : def.getProperty()) { 064 if (p.getCode().equals("notSelectable") && p.hasValue() && p.getValue() instanceof BooleanType) 065 return ((BooleanType) p.getValue()).getValue(); 066 } 067 return false; 068 } 069 070 public static void setNotSelectable(CodeSystem cs, ConceptDefinitionComponent concept) throws FHIRFormatError { 071 defineNotSelectableProperty(cs); 072 concept.addProperty().setCode("notSelectable").setValue(new BooleanType(true)); 073 } 074 075 public static void setInactive(CodeSystem cs, ConceptDefinitionComponent concept) throws FHIRFormatError { 076 defineInactiveProperty(cs); 077 concept.addProperty().setCode("inactive").setValue(new BooleanType(true)); 078 } 079 080 public static void setDeprecated(CodeSystem cs, ConceptDefinitionComponent concept, DateTimeType date) throws FHIRFormatError { 081 defineDeprecatedProperty(cs); 082 concept.addProperty().setCode("deprecationDate").setValue(date); 083 } 084 085 public static void defineNotSelectableProperty(CodeSystem cs) { 086 defineCodeSystemProperty(cs, "notSelectable", "Indicates that the code is abstract - only intended to be used as a selector for other concepts", PropertyType.BOOLEAN); 087 } 088 089 public static void defineInactiveProperty(CodeSystem cs) { 090 defineCodeSystemProperty(cs, "inactive", "True if the concept is not considered active - e.g. not a valid concept any more", PropertyType.BOOLEAN); 091 } 092 093 public static void defineDeprecatedProperty(CodeSystem cs) { 094 defineCodeSystemProperty(cs, "deprecationDate", "The date at which a concept was deprecated. Concepts that are deprecated but not inactive can still be used, but their use is discouraged", PropertyType.DATETIME); 095 } 096 097 public static void defineCodeSystemProperty(CodeSystem cs, String code, String description, PropertyType type) { 098 for (PropertyComponent p : cs.getProperty()) { 099 if (p.getCode().equals(code)) 100 return; 101 } 102 cs.addProperty().setCode(code).setDescription(description).setType(type).setUri("http://hl7.org/fhir/concept-properties#"+code); 103 } 104 105 public static String getCodeDefinition(CodeSystem cs, String code) { 106 return getCodeDefinition(cs.getConcept(), code); 107 } 108 109 private static String getCodeDefinition(List<ConceptDefinitionComponent> list, String code) { 110 for (ConceptDefinitionComponent c : list) { 111 if (c.getCode().equals(code)) 112 return c.getDefinition(); 113 String s = getCodeDefinition(c.getConcept(), code); 114 if (s != null) 115 return s; 116 } 117 return null; 118 } 119 120 public static CodeSystem makeShareable(CodeSystem cs) { 121 if (!cs.hasMeta()) 122 cs.setMeta(new Meta()); 123 for (UriType t : cs.getMeta().getProfile()) 124 if (t.getValue().equals("http://hl7.org/fhir/StructureDefinition/shareablecodesystem")) 125 return cs; 126 cs.getMeta().getProfile().add(new UriType("http://hl7.org/fhir/StructureDefinition/shareablecodesystem")); 127 return cs; 128 } 129 130 public static void setOID(CodeSystem cs, String oid) { 131 if (!oid.startsWith("urn:oid:")) 132 oid = "urn:oid:" + oid; 133 if (!cs.hasIdentifier()) 134 cs.setIdentifier(new Identifier().setSystem("urn:ietf:rfc:3986").setValue(oid)); 135 else if ("urn:ietf:rfc:3986".equals(cs.getIdentifier().getSystem()) && cs.getIdentifier().hasValue() && cs.getIdentifier().getValue().startsWith("urn:oid:")) 136 cs.getIdentifier().setValue(oid); 137 else 138 throw new Error("unable to set OID on code system"); 139 140 } 141 142 public static boolean hasOID(CodeSystem cs) { 143 return getOID(cs) != null; 144 } 145 146 public static String getOID(CodeSystem cs) { 147 if (cs.hasIdentifier() && "urn:ietf:rfc:3986".equals(cs.getIdentifier().getSystem()) && cs.getIdentifier().hasValue() && cs.getIdentifier().getValue().startsWith("urn:oid:")) 148 return cs.getIdentifier().getValue().substring(8); 149 return null; 150 } 151 152 public static boolean isInactive(CodeSystem cs, ConceptDefinitionComponent def) throws FHIRException { 153 for (ConceptPropertyComponent p : def.getProperty()) { 154 if (p.getCode().equals("status") && p.hasValueStringType()) 155 return "inactive".equals(p.getValueStringType()); 156 } 157 return false; 158 } 159 160 public static boolean isInactive(CodeSystem cs, String code) throws FHIRException { 161 ConceptDefinitionComponent def = findCode(cs.getConcept(), code); 162 if (def == null) 163 return true; 164 return isInactive(cs, def); 165 } 166 167 private static ConceptDefinitionComponent findCode(List<ConceptDefinitionComponent> list, String code) { 168 for (ConceptDefinitionComponent c : list) { 169 if (c.getCode().equals(code)) 170 return c; 171 ConceptDefinitionComponent s = findCode(c.getConcept(), code); 172 if (s != null) 173 return s; 174 } 175 return null; 176 } 177 178 public static void markStatus(CodeSystem cs, String wg, String status, String fmm) { 179 if (wg != null) { 180 if (!ExtensionUtilities.hasExtension(cs, ExtensionUtilities.EXT_WORKGROUP) || 181 (Utilities.existsInList(ExtensionUtilities.readStringExtension(cs, ExtensionUtilities.EXT_WORKGROUP), "fhir", "vocab") && !Utilities.existsInList(wg, "fhir", "vocab"))) { 182 ExtensionUtilities.setCodeExtension(cs, ExtensionUtilities.EXT_WORKGROUP, wg); 183 } 184 } 185 if (status != null) { 186 String ss = ExtensionUtilities.readStringExtension(cs, ExtensionUtilities.EXT_BALLOT_STATUS); 187 if (Utilities.noString(ss) || ssval(ss) < ssval(status)) 188 ExtensionUtilities.setStringExtension(cs, ExtensionUtilities.EXT_BALLOT_STATUS, status); 189 } 190 if (fmm != null) { 191 String sfmm = ExtensionUtilities.readStringExtension(cs, ExtensionUtilities.EXT_FMM_LEVEL); 192 if (Utilities.noString(sfmm) || Integer.parseInt(sfmm) < Integer.parseInt(fmm)) 193 ExtensionUtilities.setIntegerExtension(cs, ExtensionUtilities.EXT_FMM_LEVEL, Integer.parseInt(fmm)); 194 } 195 } 196 197 private static int ssval(String status) { 198 if ("Draft".equals("status")) 199 return 1; 200 if ("Informative".equals("status")) 201 return 2; 202 if ("External".equals("status")) 203 return 3; 204 if ("Trial Use".equals("status")) 205 return 3; 206 if ("Normative".equals("status")) 207 return 4; 208 return -1; 209 } 210 211}