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