001package org.hl7.fhir.r5.utils;
002
003import java.lang.reflect.Field;
004import java.lang.reflect.Modifier;
005
006/*
007  Copyright (c) 2011+, HL7, Inc.
008  All rights reserved.
009
010  Redistribution and use in source and binary forms, with or without modification, 
011  are permitted provided that the following conditions are met:
012
013 * Redistributions of source code must retain the above copyright notice, this 
014     list of conditions and the following disclaimer.
015 * Redistributions in binary form must reproduce the above copyright notice, 
016     this list of conditions and the following disclaimer in the documentation 
017     and/or other materials provided with the distribution.
018 * Neither the name of HL7 nor the names of its contributors may be used to 
019     endorse or promote products derived from this software without specific 
020     prior written permission.
021
022  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
023  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
024  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
025  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
026  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
027  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
028  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
029  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
030  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
031  POSSIBILITY OF SUCH DAMAGE.
032
033 */
034
035
036
037/*
038Copyright (c) 2011+, HL7, Inc
039All rights reserved.
040
041Redistribution and use in source and binary forms, with or without modification, 
042are permitted provided that the following conditions are met:
043
044 * Redistributions of source code must retain the above copyright notice, this 
045   list of conditions and the following disclaimer.
046 * Redistributions in binary form must reproduce the above copyright notice, 
047   this list of conditions and the following disclaimer in the documentation 
048   and/or other materials provided with the distribution.
049 * Neither the name of HL7 nor the names of its contributors may be used to 
050   endorse or promote products derived from this software without specific 
051   prior written permission.
052
053THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
054ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
055WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
056IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
057INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
058NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
059PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
060WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
061ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
062POSSIBILITY OF SUCH DAMAGE.
063
064 */
065
066import java.util.ArrayList;
067import java.util.HashMap;
068import java.util.Iterator;
069import java.util.List;
070import java.util.Map;
071import java.util.Set;
072import java.util.HashSet;
073
074import org.apache.commons.lang3.StringUtils;
075import org.fhir.ucum.Utilities;
076import org.hl7.fhir.exceptions.FHIRException;
077import org.hl7.fhir.r5.model.Base;
078import org.hl7.fhir.r5.model.BooleanType;
079import org.hl7.fhir.r5.model.CanonicalType;
080import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
081import org.hl7.fhir.r5.model.CodeType;
082import org.hl7.fhir.r5.model.CodeableConcept;
083import org.hl7.fhir.r5.model.Coding;
084import org.hl7.fhir.r5.model.DataType;
085import org.hl7.fhir.r5.model.DecimalType;
086import org.hl7.fhir.r5.model.DomainResource;
087import org.hl7.fhir.r5.model.Element;
088import org.hl7.fhir.r5.model.ElementDefinition;
089import org.hl7.fhir.r5.model.Extension;
090import org.hl7.fhir.r5.model.ExtensionHelper;
091import org.hl7.fhir.r5.model.Factory;
092import org.hl7.fhir.r5.model.Integer64Type;
093import org.hl7.fhir.r5.model.IntegerType;
094import org.hl7.fhir.r5.model.MarkdownType;
095import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
096import org.hl7.fhir.r5.model.PrimitiveType;
097import org.hl7.fhir.r5.model.Property;
098import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent;
099import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemType;
100import org.hl7.fhir.r5.model.StringType;
101import org.hl7.fhir.r5.model.UriType;
102import org.hl7.fhir.r5.model.UrlType;
103import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
104import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
105import org.hl7.fhir.utilities.StandardsStatus;
106import org.hl7.fhir.utilities.validation.ValidationMessage;
107import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
108import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
109import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
110
111
112public class ToolingExtensions {
113
114  public static final String EXT_ISSUE_MSG_ID = "http://hl7.org/fhir/StructureDefinition/operationoutcome-message-id";
115  public static final String EXT_ISSUE_LINE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-line";
116  public static final String EXT_ISSUE_COL = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-col";
117  public static final String EXT_OO_FILE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-file";  
118  public static final String EXT_RESOURCE_IMPLEMENTS = "http://hl7.org/fhir/StructureDefinition/structuredefinition-implements";
119  public static final String EXT_XML_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-type";
120  public static final String EXT_XML_NAME = "http://hl7.org/fhir/StructureDefinition/elementdefinition-xml-name";  
121  public static final String EXT_EXPLICIT_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name";
122
123  public static final String EXT_IGP_RESOURCES = "http://hl7.org/fhir/StructureDefinition/igpublisher-folder-resource";
124  public static final String EXT_IGP_PAGES = "http://hl7.org/fhir/StructureDefinition/igpublisher-folder-pages"; 
125  public static final String EXT_IGP_SPREADSHEET = "http://hl7.org/fhir/StructureDefinition/igpublisher-spreadsheet";
126  public static final String EXT_IGP_MAPPING_CSV = "http://hl7.org/fhir/StructureDefinition/igpublisher-mapping-csv";
127  public static final String EXT_IGP_BUNDLE = "http://hl7.org/fhir/tools/StructureDefinition/igpublisher-bundle";
128  public static final String EXT_IGP_BASE = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-base";
129  public static final String EXT_IGP_DEFNS = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-defns";
130  public static final String EXT_IGP_FORMAT = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-format";
131  public static final String EXT_IGP_SOURCE = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-source";
132  public static final String EXT_IGP_CONTAINED_RESOURCE_INFO = "http://hl7.org/fhir/tools/StructureDefinition/contained-resource-information";
133  public static final String EXT_BINARY_FORMAT_OLD = "http://hl7.org/fhir/StructureDefinition/implementationguide-resource-format";
134  public static final String EXT_BINARY_FORMAT_NEW = "http://hl7.org/fhir/tools/StructureDefinition/implementationguide-resource-format";
135  public static final String EXT_BINARY_LOGICAL = "http://hl7.org/fhir/tools/StructureDefinition/implementationguide-resource-logical";
136  public static final String EXT_IGP_RESOURCE_INFO = "http://hl7.org/fhir/tools/StructureDefinition/resource-information";
137  public static final String EXT_IGP_LOADVERSION = "http://hl7.org/fhir/StructureDefinition/igpublisher-loadversion";
138  public static final String EXT_LIST_PACKAGE = "http://hl7.org/fhir/StructureDefinition/list-packageId";
139  public static final String EXT_JSON_NAME = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-json-name";  
140  public static final String EXT_BINDING_STYLE = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-binding-style";
141  public static final String EXT_EXTENSION_STYLE = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-extension-style";
142  public static final String EXT_LOGICAL_TARGET = "http://hl7.org/fhir/tools/StructureDefinition/logical-target";
143  public static final String EXT_PROFILE_MAPPING = "http://hl7.org/fhir/tools/StructureDefinition/profile-mapping";
144  public static final String EXT_CS_ALTERNATE_USE = "http://hl7.org/fhir/StructureDefinition/alternate-code-use";
145  public static final String EXT_CS_ALTERNATE_STATUS = "http://hl7.org/fhir/StructureDefinition/alternate-code-status";
146
147  // validated
148  //  private static final String EXT_OID = "http://hl7.org/fhir/StructureDefinition/valueset-oid";
149  //  public static final String EXT_DEPRECATED = "http://hl7.org/fhir/StructureDefinition/codesystem-deprecated";
150  public static final String EXT_PATTERN = "http://hl7.org/fhir/StructureDefinition/elementdefinition-pattern";
151  public static final String EXT_ALLOWEDRESOURCE = "http://hl7.org/fhir/StructureDefinition/questionnaire-referenceResource";
152  private static final String EXT_ALLOWABLE_UNITS = "http://hl7.org/fhir/StructureDefinition/elementdefinition-allowedUnits";
153  private static final String EXT_FHIRTYPE = "http://hl7.org/fhir/StructureDefinition/questionnaire-fhirType";
154  public static final String EXT_ALLOWED_TYPE =  "http://hl7.org/fhir/StructureDefinition/operationdefinition-allowed-type";
155  public static final String EXT_BEST_PRACTICE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice"; 
156  public static final String EXT_BEST_PRACTICE_EXPLANATION = "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice-explanation"; 
157  public static final String EXT_BINDING_NAME = "http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName";
158  public static final String EXT_CONTROL = "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl";  
159  public static final String EXT_CS_COMMENT = "http://hl7.org/fhir/StructureDefinition/codesystem-concept-comments"; 
160  public static final String EXT_CS_KEYWORD = "http://hl7.org/fhir/StructureDefinition/codesystem-keyWord"; 
161  public static final String EXT_DEFINITION = "http://hl7.org/fhir/StructureDefinition/valueset-concept-definition"; 
162  public static final String EXT_DISPLAY_HINT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-display-hint";  
163  public static final String EXT_EXPAND_GROUP = "http://hl7.org/fhir/StructureDefinition/valueset-expand-group";
164  public static final String EXT_EXPAND_RULES = "http://hl7.org/fhir/StructureDefinition/valueset-expand-rules";
165  public static final String EXT_EXP_TOOCOSTLY = "http://hl7.org/fhir/StructureDefinition/valueset-toocostly";
166  public static final String EXT_FHIR_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type";
167  public static final String EXT_FMM_DERIVED = "http://hl7.org/fhir/StructureDefinition/structuredefinition-conformance-derivedFrom";
168  public static final String EXT_FMM_LEVEL = "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm";
169  public static final String EXT_FMM_SUPPORT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm-support";
170  public static final String EXT_HIERARCHY = "http://hl7.org/fhir/StructureDefinition/structuredefinition-hierarchy"; 
171  public static final String EXT_ISSUE_SOURCE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-source";  
172  public static final String EXT_MAXOCCURS = "http://hl7.org/fhir/StructureDefinition/questionnaire-maxOccurs"; 
173  public static final String EXT_MAX_DECIMALS = "http://hl7.org/fhir/StructureDefinition/maxDecimalPlaces";
174  public static final String EXT_MAX_SIZE = "http://hl7.org/fhir/StructureDefinition/maxSize";
175  public static final String EXT_MAX_VALUESET = "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet";
176  public static final String EXT_MINOCCURS = "http://hl7.org/fhir/StructureDefinition/questionnaire-minOccurs";  
177  public static final String EXT_MIN_LENGTH = "http://hl7.org/fhir/StructureDefinition/minLength";
178  public static final String EXT_MIN_VALUESET = "http://hl7.org/fhir/StructureDefinition/elementdefinition-minValueSet";
179  public static final String EXT_MUST_SUPPORT = "http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support";
180  public static final String EXT_NORMATIVE_VERSION = "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version";
181  public static final String EXT_PROFILE_ELEMENT = "http://hl7.org/fhir/StructureDefinition/elementdefinition-profile-element";
182  public static final String EXT_QTYPE = "http://hl7.org/fhir/StructureDefinition/questionnnaire-baseType";
183  public static final String EXT_Q_UNIT = "http://hl7.org/fhir/StructureDefinition/questionnaire-unit";
184  public static final String EXT_REFERENCEFILTER = "http://hl7.org/fhir/StructureDefinition/questionnaire-referenceFilter"; 
185  public static final String EXT_REGEX = "http://hl7.org/fhir/StructureDefinition/regex";  
186  public static final String EXT_RENDERED_VALUE = "http://hl7.org/fhir/StructureDefinition/rendered-value";
187  public static final String EXT_REPLACED_BY = "http://hl7.org/fhir/StructureDefinition/codesystem-replacedby";
188  public static final String EXT_RESOURCE_CATEGORY = "http://hl7.org/fhir/StructureDefinition/structuredefinition-category";
189  public static final String EXT_RESOURCE_INTERFACE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-interface";
190  public static final String EXT_SEC_CAT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-security-category";
191  public static final String EXT_STANDARDS_STATUS = "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status";
192  public static final String EXT_STANDARDS_STATUS_REASON = "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status-reason";
193  public static final String EXT_TABLE_NAME = "http://hl7.org/fhir/StructureDefinition/structuredefinition-table-name";
194  public static final String EXT_TARGET_ID = "http://hl7.org/fhir/StructureDefinition/targetElement";
195  public static final String EXT_TARGET_PATH = "http://hl7.org/fhir/StructureDefinition/targetPath";
196  public static final String EXT_TRANSLATABLE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-translatable";
197  public static final String EXT_TRANSLATION = "http://hl7.org/fhir/StructureDefinition/translation"; 
198  public static final String EXT_UNCLOSED = "http://hl7.org/fhir/StructureDefinition/valueset-unclosed";
199  public static final String EXT_VALUESET_SYSTEM = "http://hl7.org/fhir/StructureDefinition/valueset-system";
200  public static final String EXT_VS_COMMENT = "http://hl7.org/fhir/StructureDefinition/valueset-concept-comments"; 
201  public static final String EXT_VS_KEYWORD = "http://hl7.org/fhir/StructureDefinition/valueset-keyWord";  
202  public static final String EXT_WORKGROUP = "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg";
203  public static final String EXT_XML_NAMESPACE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace";
204  public static final String EXT_OLD_CONCEPTMAP_EQUIVALENCE = "http://hl7.org/fhir/1.0/StructureDefinition/extension-ConceptMap.element.target.equivalence";
205  public static final String EXT_Q_IS_SUBJ = "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject"; 
206  public static final String EXT_Q_HIDDEN = "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden";
207  public static final String EXT_Q_OTP_DISP = "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-optionalDisplay"; 
208  public static final String EXT_O_LINK_PERIOD = "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod"; 
209  public static final String EXT_Q_CHOICE_ORIENT = "http://hl7.org/fhir/StructureDefinition/questionnaire-choiceOrientation";
210  public static final String EXT_Q_DISPLAY_CAT = "http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory";
211  public static final String EXT_REND_MD = "http://hl7.org/fhir/StructureDefinition/rendering-markdown";
212  public static final String EXT_CAP_STMT_EXPECT = "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation";
213  public static final String EXT_ED_HEIRARCHY = "http://hl7.org/fhir/StructureDefinition/elementdefinition-heirarchy";
214  public static final String EXT_SD_IMPOSE_PROFILE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-imposeProfile";
215  public static final String EXT_SD_COMPLIES_WITH_PROFILE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-compliesWithProfile";
216  public static final String EXT_XML_NO_ORDER = "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-no-order";
217  public static final String EXT_DEF_TYPE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype";
218  public static final String EXT_TYPE_SPEC = "http://hl7.org/fhir/tools/StructureDefinition/type-specifier";
219  public static final String EXT_TYPE_CHARACTERISTICS = "http://hl7.org/fhir/StructureDefinition/structuredefinition-type-characteristics";
220  
221  // in the tooling IG
222  public static final String EXT_PRIVATE_BASE = "http://hl7.org/fhir/tools/";
223  public static final String EXT_BINDING_ADDITIONAL = "http://hl7.org/fhir/tools/StructureDefinition/additional-binding";
224  public static final String EXT_JSON_PROP_KEY = "http://hl7.org/fhir/tools/StructureDefinition/json-property-key";
225  public static final String EXT_JSON_EMPTY = "http://hl7.org/fhir/tools/StructureDefinition/json-empty-behavior";
226  public static final String EXT_JSON_NULLABLE = "http://hl7.org/fhir/tools/StructureDefinition/json-nullable";
227  public static final String EXT_IMPLIED_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/implied-string-prefix";
228  public static final String EXT_DATE_FORMAT = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-date-format";
229  public static final String EXT_ID_EXPECTATION = "http://hl7.org/fhir/tools/StructureDefinition/id-expectation";
230  public static final String EXT_JSON_PRIMITIVE_CHOICE = "http://hl7.org/fhir/tools/StructureDefinition/json-primitive-choice";
231  public static final String EXT_SUMMARY = "http://hl7.org/fhir/StructureDefinition/structuredefinition-summary";
232  public static final String EXT_BINDING_DEFINITION = "http://hl7.org/fhir/tools/StructureDefinition/binding-definition";
233
234
235  // unregistered? - don't know what these are used for 
236  public static final String EXT_MAPPING_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/logical-mapping-prefix";
237  public static final String EXT_MAPPING_SUFFIX = "http://hl7.org/fhir/tools/StructureDefinition/logical-mapping-suffix";
238
239  // for the v2 mapping project 
240  public static final String EXT_MAPPING_NAME = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-source-name";
241  public static final String EXT_MAPPING_TYPE = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-source-type";
242  public static final String EXT_MAPPING_CARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-source-cardinality";
243  public static final String EXT_MAPPING_TGTTYPE = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-type";
244  public static final String EXT_MAPPING_TGTCARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-cardinality";
245  
246  public static final String WEB_EXTENSION_STYLE = "http://build.fhir.org/ig/FHIR/fhir-tools-ig/format-extensions.html#extension-related-extensions";
247  public static final String WEB_BINDING_STYLE = "http://build.fhir.org/ig/FHIR/fhir-tools-ig/StructureDefinition-binding-style.html";
248  public static final String EXT_IGDEP_COMMENT = "http://hl7.org/fhir/tools/StructureDefinition/implementationguide-dependency-comment";
249  public static final String EXT_XPATH_CONSTRAINT = "http://hl7.org/fhir/4.0/StructureDefinition/extension-ElementDefinition.constraint.xpath";
250  public static final String EXT_OBLIGATION_TOOLS = "http://hl7.org/fhir/tools/StructureDefinition/obligation";
251  public static final String EXT_OBLIGATION_CORE = "http://hl7.org/fhir/StructureDefinition/obligation";
252  public static final String EXT_NO_BINDING = "http://hl7.org/fhir/tools/StructureDefinition/no-binding";
253  ;
254  
255  // specific extension helpers
256
257  public static Extension makeIssueSource(Source source) {
258    Extension ex = new Extension();
259    // todo: write this up and get it published with the pack (and handle the redirect?)
260    ex.setUrl(ToolingExtensions.EXT_ISSUE_SOURCE);
261    StringType c = new StringType();
262    c.setValue(source.toString());
263    ex.setValue(c);
264    return ex;
265  }
266
267  public static Extension makeIssueMessageId(String msgId) {
268    Extension ex = new Extension();
269    // todo: write this up and get it published with the pack (and handle the redirect?)
270    ex.setUrl(ToolingExtensions.EXT_ISSUE_MSG_ID);
271    CodeType c = new CodeType();
272    c.setValue(msgId);
273    ex.setValue(c);
274    return ex;
275  }
276
277  public static boolean hasExtension(DomainResource de, String url) {
278    return getExtension(de, url) != null;
279  }
280
281  public static boolean hasExtension(Element e, String url) {
282    return getExtension(e, url) != null;
283  }
284
285  //  public static void addStringExtension(DomainResource dr, String url, String content) {
286  //    if (!StringUtils.isBlank(content)) {
287  //      Extension ex = getExtension(dr, url);
288  //      if (ex != null)
289  //        ex.setValue(new StringType(content));
290  //      else
291  //        dr.getExtension().add(Factory.newExtension(url, new StringType(content), true));   
292  //    }
293  //  }
294
295  public static void addMarkdownExtension(DomainResource dr, String url, String content) {
296    if (!StringUtils.isBlank(content)) {
297      Extension ex = getExtension(dr, url);
298      if (ex != null)
299        ex.setValue(new StringType(content));
300      else
301        dr.getExtension().add(Factory.newExtension(url, new MarkdownType(content), true));   
302    }
303  }
304
305  public static void addStringExtension(Element e, String url, String content) {
306    if (!StringUtils.isBlank(content)) {
307      Extension ex = getExtension(e, url);
308      if (ex != null)
309        ex.setValue(new StringType(content));
310      else
311        e.getExtension().add(Factory.newExtension(url, new StringType(content), true));   
312    }
313  }
314
315  public static void addCodeExtension(Element e, String url, String content) {
316    if (!StringUtils.isBlank(content)) {
317      Extension ex = getExtension(e, url);
318      if (ex != null)
319        ex.setValue(new CodeType(content));
320      else
321        e.getExtension().add(Factory.newExtension(url, new CodeType(content), true));   
322    }
323  }
324
325  public static void addStringExtension(DomainResource e, String url, String content) {
326    if (!StringUtils.isBlank(content)) {
327      Extension ex = getExtension(e, url);
328      if (ex != null)
329        ex.setValue(new StringType(content));
330      else
331        e.getExtension().add(Factory.newExtension(url, new StringType(content), true));   
332    }
333  }
334
335
336  public static void addBooleanExtension(Element e, String url, boolean content) {
337    Extension ex = getExtension(e, url);
338    if (ex != null)
339      ex.setValue(new BooleanType(content));
340    else
341      e.getExtension().add(Factory.newExtension(url, new BooleanType(content), true));   
342  }
343
344  public static void addBooleanExtension(DomainResource e, String url, boolean content) {
345    Extension ex = getExtension(e, url);
346    if (ex != null)
347      ex.setValue(new BooleanType(content));
348    else
349      e.getExtension().add(Factory.newExtension(url, new BooleanType(content), true));   
350  }
351
352  public static void addIntegerExtension(DomainResource dr, String url, int value) {
353    Extension ex = getExtension(dr, url);
354    if (ex != null)
355      ex.setValue(new IntegerType(value));
356    else
357      dr.getExtension().add(Factory.newExtension(url, new IntegerType(value), true));   
358  }
359
360  public static void addCodeExtension(DomainResource dr, String url, String value) {
361    Extension ex = getExtension(dr, url);
362    if (ex != null)
363      ex.setValue(new CodeType(value));
364    else
365      dr.getExtension().add(Factory.newExtension(url, new CodeType(value), true));   
366  }
367
368  public static void addVSComment(ConceptSetComponent nc, String comment) {
369    if (!StringUtils.isBlank(comment))
370      nc.getExtension().add(Factory.newExtension(EXT_VS_COMMENT, Factory.newString_(comment), true));   
371  }
372  public static void addVSComment(ConceptReferenceComponent nc, String comment) {
373    if (!StringUtils.isBlank(comment))
374      nc.getExtension().add(Factory.newExtension(EXT_VS_COMMENT, Factory.newString_(comment), true));   
375  }
376
377  public static void addCSComment(ConceptDefinitionComponent nc, String comment) {
378    if (!StringUtils.isBlank(comment))
379      nc.getExtension().add(Factory.newExtension(EXT_CS_COMMENT, Factory.newString_(comment), true));   
380  }
381
382  //  public static void markDeprecated(Element nc) {
383  //    setDeprecated(nc);   
384  //  }
385  //
386
387  public static void addDefinition(Element nc, String definition) {
388    if (!StringUtils.isBlank(definition))
389      nc.getExtension().add(Factory.newExtension(EXT_DEFINITION, Factory.newString_(definition), true));   
390  }
391
392  public static void addDisplayHint(Element def, String hint) {
393    if (!StringUtils.isBlank(hint))
394      def.getExtension().add(Factory.newExtension(EXT_DISPLAY_HINT, Factory.newString_(hint), true));   
395  }
396
397  public static String getDisplayHint(Element def) {
398    return readStringExtension(def, EXT_DISPLAY_HINT);    
399  }
400
401  public static String readStringExtension(Element c, String uri) {
402    Extension ex = ExtensionHelper.getExtension(c, uri);
403    if (ex == null)
404      return null;
405    if (ex.getValue() instanceof UriType)
406      return ((UriType) ex.getValue()).getValue();
407    if (ex.getValue() instanceof CanonicalType)
408      return ((CanonicalType) ex.getValue()).getValue();
409    if (ex.getValue() instanceof CodeType)
410      return ((CodeType) ex.getValue()).getValue();
411    if (ex.getValue() instanceof IntegerType)
412      return ((IntegerType) ex.getValue()).asStringValue();
413    if (ex.getValue() instanceof Integer64Type)
414      return ((Integer64Type) ex.getValue()).asStringValue();
415    if (ex.getValue() instanceof DecimalType)
416      return ((DecimalType) ex.getValue()).asStringValue();
417    if ((ex.getValue() instanceof MarkdownType))
418      return ((MarkdownType) ex.getValue()).getValue();
419    if ((ex.getValue() instanceof PrimitiveType))
420      return ((PrimitiveType) ex.getValue()).primitiveValue();
421    if (!(ex.getValue() instanceof StringType))
422      return null;
423    return ((StringType) ex.getValue()).getValue();
424  }
425
426  public static String readStringExtension(DomainResource c, String uri) {
427    Extension ex = getExtension(c, uri);
428    if (ex == null)
429      return null;
430    if ((ex.getValue() instanceof StringType))
431      return ((StringType) ex.getValue()).getValue();
432    if ((ex.getValue() instanceof UriType))
433      return ((UriType) ex.getValue()).getValue();
434    if (ex.getValue() instanceof CodeType)
435      return ((CodeType) ex.getValue()).getValue();
436    if (ex.getValue() instanceof IntegerType)
437      return ((IntegerType) ex.getValue()).asStringValue();
438    if (ex.getValue() instanceof Integer64Type)
439      return ((Integer64Type) ex.getValue()).asStringValue();
440    if (ex.getValue() instanceof DecimalType)
441      return ((DecimalType) ex.getValue()).asStringValue();
442    if ((ex.getValue() instanceof MarkdownType))
443      return ((MarkdownType) ex.getValue()).getValue();
444    return null;
445  }
446
447  @SuppressWarnings("unchecked")
448  public static PrimitiveType<DataType> readPrimitiveExtension(DomainResource c, String uri) {
449    Extension ex = getExtension(c, uri);
450    if (ex == null)
451      return null;
452    return (PrimitiveType<DataType>) ex.getValue();
453  }
454
455  public static boolean findStringExtension(Element c, String uri) {
456    Extension ex = ExtensionHelper.getExtension(c, uri);
457    if (ex == null)
458      return false;
459    if (!(ex.getValue() instanceof StringType))
460      return false;
461    return !StringUtils.isBlank(((StringType) ex.getValue()).getValue());
462  }
463
464  public static Boolean readBooleanExtension(Element c, String uri) {
465    Extension ex = ExtensionHelper.getExtension(c, uri);
466    if (ex == null)
467      return null;
468    if (!(ex.getValue() instanceof BooleanType))
469      return null;
470    return ((BooleanType) ex.getValue()).getValue();
471  }
472
473  public static boolean findBooleanExtension(Element c, String uri) {
474    Extension ex = ExtensionHelper.getExtension(c, uri);
475    if (ex == null)
476      return false;
477    if (!(ex.getValue() instanceof BooleanType))
478      return false;
479    return true;
480  }
481
482  public static Boolean readBooleanExtension(DomainResource c, String uri) {
483    Extension ex = ExtensionHelper.getExtension(c, uri);
484    if (ex == null)
485      return null;
486    if (!(ex.getValue() instanceof BooleanType))
487      return null;
488    return ((BooleanType) ex.getValue()).getValue();
489  }
490
491  public static boolean readBoolExtension(DomainResource c, String uri) {
492    Extension ex = ExtensionHelper.getExtension(c, uri);
493    if (ex == null)
494      return false;
495    if (!(ex.getValue() instanceof BooleanType))
496      return false;
497    return ((BooleanType) ex.getValue()).getValue();
498  }
499
500  public static boolean readBoolExtension(Element e, String uri) {
501    Extension ex = ExtensionHelper.getExtension(e, uri);
502    if (ex == null)
503      return false;
504    if (!(ex.getValue() instanceof BooleanType))
505      return false;
506    if (!(ex.getValue().hasPrimitiveValue()))
507      return false;
508    return ((BooleanType) ex.getValue()).getValue();
509  }
510
511  public static boolean findBooleanExtension(DomainResource c, String uri) {
512    Extension ex = ExtensionHelper.getExtension(c, uri);
513    if (ex == null)
514      return false;
515    if (!(ex.getValue() instanceof BooleanType))
516      return false;
517    return true;
518  }
519
520  public static String getCSComment(ConceptDefinitionComponent c) {
521    return readStringExtension(c, EXT_CS_COMMENT);    
522  }
523  //
524  //  public static Boolean getDeprecated(Element c) {
525  //    return readBooleanExtension(c, EXT_DEPRECATED);    
526  //  }
527
528  public static boolean hasCSComment(ConceptDefinitionComponent c) {
529    return findStringExtension(c, EXT_CS_COMMENT);    
530  }
531
532  //  public static boolean hasDeprecated(Element c) {
533  //    return findBooleanExtension(c, EXT_DEPRECATED);    
534  //  }
535
536  public static void addFlyOver(QuestionnaireItemComponent item, String text, String linkId){
537    if (!StringUtils.isBlank(text)) {
538      QuestionnaireItemComponent display = item.addItem();
539      display.setType(QuestionnaireItemType.DISPLAY);
540      display.setText(text);
541      display.setLinkId(linkId);
542      display.getExtension().add(Factory.newExtension(EXT_CONTROL, Factory.newCodeableConcept("flyover", "http://hl7.org/fhir/questionnaire-item-control", "Fly-over"), true));
543    }
544  }
545
546  public static void addMin(QuestionnaireItemComponent item, int min) {
547    item.getExtension().add(Factory.newExtension(EXT_MINOCCURS, Factory.newInteger(min), true));
548  }
549
550  public static void addMax(QuestionnaireItemComponent item, int max) {
551    item.getExtension().add(Factory.newExtension(EXT_MAXOCCURS, Factory.newInteger(max), true));
552  }
553
554  public static void addFhirType(QuestionnaireItemComponent group, String value) {
555    group.getExtension().add(Factory.newExtension(EXT_FHIRTYPE, Factory.newString_(value), true));       
556  }
557
558  public static void addControl(QuestionnaireItemComponent group, String value) {
559    group.getExtension().add(Factory.newExtension(EXT_CONTROL, Factory.newCodeableConcept(value, "http://hl7.org/fhir/questionnaire-item-control", value), true));
560  }
561
562  public static void addAllowedResource(QuestionnaireItemComponent group, String value) {
563    group.getExtension().add(Factory.newExtension(EXT_ALLOWEDRESOURCE, Factory.newCode(value), true));       
564  }
565
566  public static void addReferenceFilter(QuestionnaireItemComponent group, String value) {
567    group.getExtension().add(Factory.newExtension(EXT_REFERENCEFILTER, Factory.newString_(value), true));       
568  }
569
570  //  public static void addIdentifier(Element element, Identifier value) {
571  //    element.getExtension().add(Factory.newExtension(EXT_IDENTIFIER, value, true));       
572  //  }
573
574  /**
575   * @param name the identity of the extension of interest
576   * @return The extension, if on this element, else null
577   */
578  public static Extension getExtension(DomainResource resource, String name) {
579    if (resource == null || name == null)
580      return null;
581    if (!resource.hasExtension())
582      return null;
583    for (Extension e : resource.getExtension()) {
584      if (name.equals(e.getUrl()))
585        return e;
586    }
587    return null;
588  }
589
590  public static Extension getExtension(Element el, String name) {
591    if (name == null)
592      return null;
593    if (!el.hasExtension())
594      return null;
595    for (Extension e : el.getExtension()) {
596      if (name.equals(e.getUrl()))
597        return e;
598    }
599    return null;
600  }
601
602  public static void setStringExtension(DomainResource resource, String uri, String value) {
603    if (Utilities.noString(value))
604      return;
605    Extension ext = getExtension(resource, uri);
606    if (ext != null)
607      ext.setValue(new StringType(value));
608    else
609      resource.getExtension().add(new Extension(uri).setValue(new StringType(value)));
610  }
611
612  public static void setStringExtension(Element resource, String uri, String value) {
613    if (Utilities.noString(value))
614      return;
615    Extension ext = getExtension(resource, uri);
616    if (ext != null)
617      ext.setValue(new StringType(value));
618    else
619      resource.getExtension().add(new Extension(uri).setValue(new StringType(value)));
620  }
621
622  public static void setUriExtension(DomainResource resource, String uri, String value) {
623    if (Utilities.noString(value))
624      return;
625    Extension ext = getExtension(resource, uri);
626    if (ext != null)
627      ext.setValue(new UriType(value));
628    else
629      resource.getExtension().add(new Extension(uri).setValue(new UriType(value)));
630  }
631
632  public static void setUriExtension(Element resource, String uri, String value) {
633    if (Utilities.noString(value))
634      return;
635    Extension ext = getExtension(resource, uri);
636    if (ext != null)
637      ext.setValue(new UriType(value));
638    else
639      resource.getExtension().add(new Extension(uri).setValue(new UriType(value)));
640  }
641
642  public static void setUrlExtension(DomainResource resource, String uri, String value) {
643    if (Utilities.noString(value))
644      return;
645    Extension ext = getExtension(resource, uri);
646    if (ext != null)
647      ext.setValue(new UrlType(value));
648    else
649      resource.getExtension().add(new Extension(uri).setValue(new UrlType(value)));
650  }
651
652  public static void setUrlExtension(Element resource, String uri, String value) {
653    if (Utilities.noString(value))
654      return;
655    Extension ext = getExtension(resource, uri);
656    if (ext != null)
657      ext.setValue(new UrlType(value));
658    else
659      resource.getExtension().add(new Extension(uri).setValue(new UrlType(value)));
660  }
661
662  public static void setCodeExtension(DomainResource resource, String uri, String value) {
663    if (Utilities.noString(value))
664      return;
665
666    Extension ext = getExtension(resource, uri);
667    if (ext != null)
668      ext.setValue(new CodeType(value));
669    else
670      resource.getExtension().add(new Extension(uri).setValue(new CodeType(value)));
671  }
672
673  public static void setCodeExtension(Element element, String uri, String value) {
674    if (Utilities.noString(value))
675      return;
676
677    Extension ext = getExtension(element, uri);
678    if (ext != null)
679      ext.setValue(new CodeType(value));
680    else
681      element.getExtension().add(new Extension(uri).setValue(new CodeType(value)));
682  }
683
684  public static void setIntegerExtension(DomainResource resource, String uri, int value) {
685    Extension ext = getExtension(resource, uri);
686    if (ext != null)
687      ext.setValue(new IntegerType(value));
688    else
689      resource.getExtension().add(new Extension(uri).setValue(new IntegerType(value)));
690  }
691
692  //  public static String getOID(CodeSystem define) {
693  //    return readStringExtension(define, EXT_OID);    
694  //  }
695  //
696  //  public static String getOID(ValueSet vs) {
697  //    return readStringExtension(vs, EXT_OID);    
698  //  }
699  //
700  //  public static void setOID(CodeSystem define, String oid) throws FHIRFormatError, URISyntaxException {
701  //    if (!oid.startsWith("urn:oid:"))
702  //      throw new FHIRFormatError("Error in OID format");
703  //    if (oid.startsWith("urn:oid:urn:oid:"))
704  //      throw new FHIRFormatError("Error in OID format");
705  //    if (!hasExtension(define, EXT_OID))
706  //    define.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false));       
707  //    else if (!oid.equals(readStringExtension(define, EXT_OID)))
708  //      throw new Error("Attempt to assign multiple OIDs to a code system");
709  //  }
710  //  public static void setOID(ValueSet vs, String oid) throws FHIRFormatError, URISyntaxException {
711  //    if (!oid.startsWith("urn:oid:"))
712  //      throw new FHIRFormatError("Error in OID format");
713  //    if (oid.startsWith("urn:oid:urn:oid:"))
714  //      throw new FHIRFormatError("Error in OID format");
715  //    if (!hasExtension(vs, EXT_OID))
716  //    vs.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false));       
717  //    else if (!oid.equals(readStringExtension(vs, EXT_OID)))
718  //      throw new Error("Attempt to assign multiple OIDs to value set "+vs.getName()+" ("+vs.getUrl()+"). Has "+readStringExtension(vs, EXT_OID)+", trying to add "+oid);
719  //  }
720
721  public static boolean hasLanguageTranslation(Element element, String lang) {
722    for (Extension e : element.getExtension()) {
723      if (e.getUrl().equals(EXT_TRANSLATION)) {
724        Extension e1 = ExtensionHelper.getExtension(e, "lang");
725
726        if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang))
727          return true;
728      }
729    }
730    return false;
731  }
732
733  public static String getLanguageTranslation(Element element, String lang) {
734    for (Extension e : element.getExtension()) {
735      if (e.getUrl().equals(EXT_TRANSLATION)) {
736        Extension e1 = ExtensionHelper.getExtension(e, "lang");
737
738        if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang)) {
739          e1 = ExtensionHelper.getExtension(e, "content");
740          return ((StringType) e.getValue()).getValue();
741        }
742      }
743    }
744    return null;
745  }
746
747  public static void addLanguageTranslation(Element element, String lang, String value) {
748    if (Utilities.noString(lang) || Utilities.noString(value))
749      return;
750
751    Extension extension = new Extension().setUrl(EXT_TRANSLATION);
752    extension.addExtension().setUrl("lang").setValue(new CodeType(lang));
753    extension.addExtension().setUrl("content").setValue(new StringType(value));
754    element.getExtension().add(extension);
755  }
756
757  public static boolean hasAllowedUnits(ElementDefinition eld) {
758    for (Extension e : eld.getExtension()) 
759      if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) 
760        return true;
761    return false;
762  }
763
764  public static DataType getAllowedUnits(ElementDefinition eld) {
765    for (Extension e : eld.getExtension()) 
766      if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) 
767        return e.getValue();
768    return null;
769  }
770
771  public static void setAllowableUnits(ElementDefinition eld, CodeableConcept cc) {
772    for (Extension e : eld.getExtension()) 
773      if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) {
774        e.setValue(cc);
775        return;
776      }
777    eld.getExtension().add(new Extension().setUrl(EXT_ALLOWABLE_UNITS).setValue(cc));
778  }
779
780  public static List<Extension> getExtensions(Element element, String url) {
781    List<Extension> results = new ArrayList<Extension>();
782    for (Extension ex : element.getExtension())
783      if (ex.getUrl().equals(url))
784        results.add(ex);
785    return results;
786  }
787
788  public static List<Extension> getExtensions(DomainResource resource, String url) {
789    List<Extension> results = new ArrayList<Extension>();
790    for (Extension ex : resource.getExtension())
791      if (ex.getUrl().equals(url))
792        results.add(ex);
793    return results;
794  }
795
796  //  public static void addDEReference(DataElement de, String value) {
797  //    for (Extension e : de.getExtension()) 
798  //      if (e.getUrl().equals(EXT_CIMI_REFERENCE)) {
799  //        e.setValue(new UriType(value));
800  //        return;
801  //      }
802  //    de.getExtension().add(new Extension().setUrl(EXT_CIMI_REFERENCE).setValue(new UriType(value)));
803  //  }
804
805  //  public static void setDeprecated(Element nc) {
806  //    for (Extension e : nc.getExtension()) 
807  //      if (e.getUrl().equals(EXT_DEPRECATED)) {
808  //        e.setValue(new BooleanType(true));
809  //        return;
810  //      }
811  //    nc.getExtension().add(new Extension().setUrl(EXT_DEPRECATED).setValue(new BooleanType(true)));    
812  //  }
813
814  public static void setExtension(Element focus, String url, Coding c) {
815    for (Extension e : focus.getExtension()) 
816      if (e.getUrl().equals(url)) {
817        e.setValue(c);
818        return;
819      }
820    focus.getExtension().add(new Extension().setUrl(url).setValue(c));    
821  }
822
823  public static void removeExtension(DomainResource focus, String url) {
824    Iterator<Extension> i = focus.getExtension().iterator();
825    while (i.hasNext()) {
826      Extension e = i.next(); // must be called before you can call i.remove()
827      if (e.getUrl().equals(url)) {
828        i.remove();
829      }
830    }
831  }
832
833  public static void removeExtension(Element focus, String url) {
834    Iterator<Extension> i = focus.getExtension().iterator();
835    while (i.hasNext()) {
836      Extension e = i.next(); // must be called before you can call i.remove()
837      if (e.getUrl().equals(url)) {
838        i.remove();
839      }
840    }
841  }
842
843  public static int readIntegerExtension(DomainResource dr, String uri, int defaultValue) {
844    Extension ex = ExtensionHelper.getExtension(dr, uri);
845    if (ex == null)
846      return defaultValue;
847    if (ex.getValue() instanceof IntegerType)
848      return ((IntegerType) ex.getValue()).getValue();
849    throw new Error("Unable to read extension "+uri+" as an integer");
850  }
851
852  public static int readIntegerExtension(Element e, String uri, int defaultValue) {
853    Extension ex = ExtensionHelper.getExtension(e, uri);
854    if (ex == null)
855      return defaultValue;
856    if (ex.getValue() instanceof IntegerType)
857      return ((IntegerType) ex.getValue()).getValue();
858    throw new Error("Unable to read extension "+uri+" as an integer");
859  }
860
861  public static Map<String, String> getLanguageTranslations(Element e) {
862    Map<String, String> res = new HashMap<String, String>();
863    for (Extension ext : e.getExtension()) {
864      if (ext.getUrl().equals(EXT_TRANSLATION)) {
865        String lang = readStringExtension(ext, "lang");
866        String value = readStringExtension(ext, "content");
867        res.put(lang,  value);
868      }
869    }
870    return res;
871  }
872
873  public static StandardsStatus getStandardsStatus(DomainResource dr) throws FHIRException {
874    return StandardsStatus.fromCode(ToolingExtensions.readStringExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS));
875  }
876
877  public static StandardsStatus getStandardsStatus(Element e) throws FHIRException {
878    return StandardsStatus.fromCode(ToolingExtensions.readStringExtension(e, ToolingExtensions.EXT_STANDARDS_STATUS));
879  }
880
881  public static void setStandardsStatus(DomainResource dr, StandardsStatus status, String normativeVersion) {
882    if (status == null)
883      ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS);
884    else
885      ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS, status.toCode());
886    if (normativeVersion == null)
887      ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION);
888    else
889      ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION, normativeVersion);
890  }
891
892  public static void setStandardsStatus(Element dr, StandardsStatus status, String normativeVersion) {
893    if (status == null)
894      ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS);
895    else
896      ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS, status.toCode());
897    if (normativeVersion == null)
898      ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION);
899    else
900      ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION, normativeVersion);
901  }
902
903  public static ValidationMessage readValidationMessage(OperationOutcomeIssueComponent issue, Source source) {
904    ValidationMessage vm = new ValidationMessage();
905    vm.setSource(source);
906    vm.setLevel(mapSeverity(issue.getSeverity()));
907    vm.setType(mapType(issue.getCode()));
908    if (issue.hasExtension(ToolingExtensions.EXT_ISSUE_LINE))
909      vm.setLine(ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_LINE, 0));
910    if (issue.hasExtension(ToolingExtensions.EXT_ISSUE_COL))
911      vm.setCol(ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_COL, 0));
912    if (issue.hasExpression())
913      vm.setLocation(issue.getExpression().get(0).asStringValue());
914    vm.setMessage(issue.getDetails().getText());
915    if (issue.hasExtension("http://hl7.org/fhir/StructureDefinition/rendering-xhtml"))
916      vm.setHtml(ToolingExtensions.readStringExtension(issue, "http://hl7.org/fhir/StructureDefinition/rendering-xhtml"));
917    return vm;
918  }
919
920  private static IssueType mapType(org.hl7.fhir.r5.model.OperationOutcome.IssueType code) {
921    switch (code) {
922    case BUSINESSRULE: return IssueType.BUSINESSRULE;
923    case CODEINVALID: return IssueType.CODEINVALID;
924    case CONFLICT: return IssueType.CONFLICT;
925    case DELETED: return IssueType.DELETED;
926    case DUPLICATE: return IssueType.DUPLICATE;
927    case EXCEPTION: return IssueType.EXCEPTION;
928    case EXPIRED: return IssueType.EXPIRED;
929    case EXTENSION: return IssueType.EXTENSION;
930    case FORBIDDEN: return IssueType.FORBIDDEN;
931    case INCOMPLETE: return IssueType.INCOMPLETE;
932    case INFORMATIONAL: return IssueType.INFORMATIONAL;
933    case INVALID: return IssueType.INVALID;
934    case INVARIANT: return IssueType.INVARIANT;
935    case LOCKERROR: return IssueType.LOCKERROR;
936    case LOGIN: return IssueType.LOGIN;
937    case MULTIPLEMATCHES: return IssueType.MULTIPLEMATCHES;
938    case NOSTORE: return IssueType.NOSTORE;
939    case NOTFOUND: return IssueType.NOTFOUND;
940    case NOTSUPPORTED: return IssueType.NOTSUPPORTED;
941    case NULL: return IssueType.NULL;
942    case PROCESSING: return IssueType.PROCESSING;
943    case REQUIRED: return IssueType.REQUIRED;
944    case SECURITY: return IssueType.SECURITY;
945    case STRUCTURE: return IssueType.STRUCTURE;
946    case SUPPRESSED: return IssueType.SUPPRESSED;
947    case THROTTLED: return IssueType.THROTTLED;
948    case TIMEOUT: return IssueType.TIMEOUT;
949    case TOOCOSTLY: return IssueType.TOOCOSTLY;
950    case TOOLONG: return IssueType.TOOLONG;
951    case TRANSIENT: return IssueType.TRANSIENT;
952    case UNKNOWN: return IssueType.UNKNOWN;
953    case VALUE: return IssueType.VALUE;
954    default: return null;
955    }
956  }
957
958  private static IssueSeverity mapSeverity(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity severity) {
959    switch (severity) {
960    case ERROR: return IssueSeverity.ERROR;
961    case FATAL: return IssueSeverity.FATAL;
962    case INFORMATION: return IssueSeverity.INFORMATION;
963    case WARNING: return IssueSeverity.WARNING;
964    default: return null;
965    }
966  }
967
968  public static String getPresentation(PrimitiveType<?> type) {
969    if (type.hasExtension(EXT_RENDERED_VALUE))
970      return readStringExtension(type, EXT_RENDERED_VALUE);
971    return type.primitiveValue();
972  }
973
974  public static String getPresentation(Element holder, PrimitiveType<?> type) {
975    if (holder.hasExtension(EXT_RENDERED_VALUE))
976      return readStringExtension(holder, EXT_RENDERED_VALUE);
977    if (type.hasExtension(EXT_RENDERED_VALUE))
978      return readStringExtension(type, EXT_RENDERED_VALUE);
979    return type.primitiveValue();
980  }
981
982  //  public static boolean hasOID(ValueSet vs) {
983  //    return hasExtension(vs, EXT_OID);
984  //  }
985  //  
986  //  public static boolean hasOID(CodeSystem cs) {
987  //    return hasExtension(cs, EXT_OID);
988  //  }
989  //  
990  public static void addUrlExtension(Element e, String url, String content) {
991    if (!StringUtils.isBlank(content)) {
992      Extension ex = getExtension(e, url);
993      if (ex != null)
994        ex.setValue(new UrlType(content));
995      else
996        e.getExtension().add(Factory.newExtension(url, new UrlType(content), true));   
997    }
998  }
999
1000  public static void addUrlExtension(DomainResource dr, String url, String value) {
1001    Extension ex = getExtension(dr, url);
1002    if (ex != null)
1003      ex.setValue(new UrlType(value));
1004    else
1005      dr.getExtension().add(Factory.newExtension(url, new UrlType(value), true));   
1006  }
1007
1008  public static void addUriExtension(Element e, String url, String content) {
1009    if (!StringUtils.isBlank(content)) {
1010      Extension ex = getExtension(e, url);
1011      if (ex != null)
1012        ex.setValue(new UriType(content));
1013      else
1014        e.getExtension().add(Factory.newExtension(url, new UriType(content), true));   
1015    }
1016  }
1017
1018  public static void addUriExtension(DomainResource dr, String url, String value) {
1019    Extension ex = getExtension(dr, url);
1020    if (ex != null)
1021      ex.setValue(new UriType(value));
1022    else
1023      dr.getExtension().add(Factory.newExtension(url, new UriType(value), true));   
1024  }
1025
1026  public static boolean usesExtension(String url, Base base) {
1027    if ("Extension".equals(base.fhirType())) {
1028      Property p = base.getNamedProperty("url");
1029      for (Base b : p.getValues()) {
1030        if (url.equals(b.primitiveValue())) {
1031          return true;
1032        }
1033      }
1034    }
1035
1036    for (Property p : base.children() ) {
1037      for (Base v : p.getValues()) {
1038        if (usesExtension(url, v)) {
1039          return true;
1040        }
1041      }
1042    }
1043    return false;
1044  }
1045
1046  private static Set<String> cachedConsts;
1047  
1048  public static Set<String> allConsts() {
1049    if (cachedConsts == null) {
1050      Set<String> list = new HashSet<>();
1051      for (Field field : ToolingExtensions.class.getDeclaredFields()) {
1052        int modifiers = field.getModifiers();
1053        if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
1054          try {
1055            list.add(field.get(field.getType()).toString());
1056          } catch (Exception e) {
1057          }
1058        }
1059      }
1060      cachedConsts = list;
1061    }
1062    return cachedConsts;
1063  }
1064
1065  public static boolean hasExtensions(ElementDefinition d, String... urls) {
1066    for (String url : urls) {
1067      if (d.hasExtension(url)) {
1068        return true;
1069      }
1070    }
1071    return false;
1072  }
1073
1074  public static int countExtensions(ElementDefinition d, String... urls) {
1075    int res = 0;
1076    for (String url : urls) {
1077      if (d.hasExtension(url)) {
1078        res++;
1079      }
1080    }
1081    return res;
1082  }
1083
1084  public static final String EXT_OBLIGATION_PROFILE_FLAG = "http://hl7.org/fhir/tools/StructureDefinition/obligation-profile";
1085  public static final String EXT_OBLIGATION_INHERITS = "http://hl7.org/fhir/tools/StructureDefinition/inherit-obligations";
1086
1087}