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