001package org.hl7.fhir.r5.extensions;
002
003import org.apache.commons.lang3.StringUtils;
004import org.hl7.fhir.exceptions.FHIRException;
005import org.hl7.fhir.r5.model.*;
006
007import org.hl7.fhir.utilities.StandardsStatus;
008import org.hl7.fhir.utilities.Utilities;
009import org.hl7.fhir.utilities.validation.ValidationMessage;
010
011import java.lang.reflect.Field;
012import java.lang.reflect.Modifier;
013import java.math.BigDecimal;
014import java.util.*;
015
016public class ExtensionUtilities {
017
018  // specific extension helpers
019
020  public static Extension makeIssueSource(ValidationMessage.Source source) {
021    Extension ex = new Extension();
022    // todo: write this up and get it published with the pack (and handle the redirect?)
023    ex.setUrl(ExtensionDefinitions.EXT_ISSUE_SOURCE);
024    StringType c = new StringType();
025    c.setValue(source.toString());
026    ex.setValue(c);
027    return ex;
028  }
029
030  public static Extension makeIssueMessageId(String msgId) {
031    Extension ex = new Extension();
032    // todo: write this up and get it published with the pack (and handle the redirect?)
033    ex.setUrl(ExtensionDefinitions.EXT_ISSUE_MSG_ID);
034    CodeType c = new CodeType();
035    c.setValue(msgId);
036    ex.setValue(c);
037    return ex;
038  }
039
040  public static boolean hasExtension(DomainResource de, String url) {
041    return getExtension(de, url) != null;
042  }
043
044  public static boolean hasExtension(Element e, String url) {
045    return getExtension(e, url) != null;
046  }
047
048  //  public static void addStringExtension(DomainResource dr, String url, String content) {
049  //    if (!StringUtils.isBlank(content)) {
050  //      Extension ex = getExtension(dr, url);
051  //      if (ex != null)
052  //        ex.setValue(new StringType(content));
053  //      else
054  //        dr.getExtension().add(Factory.newExtension(url, new StringType(content), true));
055  //    }
056  //  }
057
058  public static void addMarkdownExtension(DomainResource dr, String url, String content) {
059    if (!StringUtils.isBlank(content)) {
060      Extension ex = getExtension(dr, url);
061      if (ex != null)
062        ex.setValue(new StringType(content));
063      else
064        dr.getExtension().add(Factory.newExtension(url, new MarkdownType(content), true));
065    }
066  }
067
068  public static void addStringExtension(Element e, String url, String content) {
069    if (!StringUtils.isBlank(content)) {
070      Extension ex = getExtension(e, url);
071      if (ex != null)
072        ex.setValue(new StringType(content));
073      else
074        e.getExtension().add(Factory.newExtension(url, new StringType(content), true));
075    }
076  }
077
078  public static void addCodeExtension(Element e, String url, String content) {
079    if (!StringUtils.isBlank(content)) {
080      Extension ex = getExtension(e, url);
081      if (ex != null)
082        ex.setValue(new CodeType(content));
083      else
084        e.getExtension().add(Factory.newExtension(url, new CodeType(content), true));
085    }
086  }
087
088  public static void addStringExtension(DomainResource e, String url, String content) {
089    if (!StringUtils.isBlank(content)) {
090      Extension ex = getExtension(e, url);
091      if (ex != null)
092        ex.setValue(new StringType(content));
093      else
094        e.getExtension().add(Factory.newExtension(url, new StringType(content), true));
095    }
096  }
097
098
099  public static void addBooleanExtension(Element e, String url, boolean content) {
100    Extension ex = getExtension(e, url);
101    if (ex != null)
102      ex.setValue(new BooleanType(content));
103    else
104      e.getExtension().add(Factory.newExtension(url, new BooleanType(content), true));
105  }
106
107  public static void addBooleanExtension(DomainResource e, String url, boolean content) {
108    Extension ex = getExtension(e, url);
109    if (ex != null)
110      ex.setValue(new BooleanType(content));
111    else
112      e.getExtension().add(Factory.newExtension(url, new BooleanType(content), true));
113  }
114
115  public static void addIntegerExtension(DomainResource dr, String url, int value) {
116    Extension ex = getExtension(dr, url);
117    if (ex != null)
118      ex.setValue(new IntegerType(value));
119    else
120      dr.getExtension().add(Factory.newExtension(url, new IntegerType(value), true));
121  }
122
123  public static void addCodeExtension(DomainResource dr, String url, String value) {
124    Extension ex = getExtension(dr, url);
125    if (ex != null)
126      ex.setValue(new CodeType(value));
127    else
128      dr.getExtension().add(Factory.newExtension(url, new CodeType(value), true));
129  }
130
131  public static void addVSComment(ValueSet.ConceptSetComponent nc, String comment) {
132    if (!StringUtils.isBlank(comment))
133      nc.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_VS_COMMENT, Factory.newString_(comment), true));
134  }
135  public static void addVSComment(ValueSet.ConceptReferenceComponent nc, String comment) {
136    if (!StringUtils.isBlank(comment))
137      nc.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_VS_COMMENT, Factory.newString_(comment), true));
138  }
139
140  public static void addCSComment(CodeSystem.ConceptDefinitionComponent nc, String comment) {
141    if (!StringUtils.isBlank(comment))
142      nc.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_CS_COMMENT, Factory.newString_(comment), true));
143  }
144
145  //  public static void markDeprecated(Element nc) {
146  //    setDeprecated(nc);
147  //  }
148  //
149
150  public static void addDefinition(Element nc, String definition) {
151    if (!StringUtils.isBlank(definition))
152      nc.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_DEFINITION, Factory.newString_(definition), true));
153  }
154
155  public static void addDisplayHint(Element def, String hint) {
156    if (!StringUtils.isBlank(hint))
157      def.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_DISPLAY_HINT, Factory.newString_(hint), true));
158  }
159
160  public static String getDisplayHint(Element def) {
161    return readStringExtension(def, ExtensionDefinitions.EXT_DISPLAY_HINT);
162  }
163
164  public static String readStringExtension(Element c, String... uris) {
165    for (String uri : uris) {
166      if (hasExtension(c, uri)) {
167        return readStringExtension(c, uri);
168      }
169    }
170    return null;
171  }
172
173  public static String readStringFromExtension(Extension ext) {
174    if (ext.hasValue() && ext.getValue().isPrimitive()) {
175      return ext.getValue().primitiveValue();
176    }
177    return null;
178  }
179
180  public static String readStringExtension(Element c, String uri) {
181    Extension ex = ExtensionHelper.getExtension(c, uri);
182    if (ex == null)
183      return null;
184    if (ex.getValue() instanceof UriType)
185      return ((UriType) ex.getValue()).getValue();
186    if (ex.getValue() instanceof CanonicalType)
187      return ((CanonicalType) ex.getValue()).getValue();
188    if (ex.getValue() instanceof CodeType)
189      return ((CodeType) ex.getValue()).getValue();
190    if (ex.getValue() instanceof IntegerType)
191      return ((IntegerType) ex.getValue()).asStringValue();
192    if (ex.getValue() instanceof Integer64Type)
193      return ((Integer64Type) ex.getValue()).asStringValue();
194    if (ex.getValue() instanceof DecimalType)
195      return ((DecimalType) ex.getValue()).asStringValue();
196    if ((ex.getValue() instanceof MarkdownType))
197      return ((MarkdownType) ex.getValue()).getValue();
198    if ((ex.getValue() instanceof PrimitiveType))
199      return ((PrimitiveType) ex.getValue()).primitiveValue();
200    if (!(ex.getValue() instanceof StringType))
201      return null;
202    return ((StringType) ex.getValue()).getValue();
203  }
204
205  public static List<String> readStringExtensions(Element c, String uri) {
206    List<String> res = new ArrayList<>();
207    List<Extension> list = ExtensionHelper.getExtensionList(c, uri);
208    for (Extension ex : list) {
209      if (ex != null) {
210        if (ex.getValue() instanceof UriType)
211          res.add(((UriType) ex.getValue()).getValue());
212        if (ex.getValue() instanceof CanonicalType)
213          res.add(((CanonicalType) ex.getValue()).getValue());
214        if (ex.getValue() instanceof CodeType)
215          res.add(((CodeType) ex.getValue()).getValue());
216        if (ex.getValue() instanceof IntegerType)
217          res.add(((IntegerType) ex.getValue()).asStringValue());
218        if (ex.getValue() instanceof Integer64Type)
219          res.add(((Integer64Type) ex.getValue()).asStringValue());
220        if (ex.getValue() instanceof DecimalType)
221          res.add(((DecimalType) ex.getValue()).asStringValue());
222        if ((ex.getValue() instanceof MarkdownType))
223          res.add(((MarkdownType) ex.getValue()).getValue());
224        if ((ex.getValue() instanceof PrimitiveType))
225          res.add(((PrimitiveType) ex.getValue()).primitiveValue());
226        if ((ex.getValue() instanceof StringType))
227          res.add(((StringType) ex.getValue()).getValue());
228      }
229    }
230    return res;
231  }
232
233  public static String readStringExtension(DomainResource c, String... uris) {
234    for (String uri : uris) {
235      if (hasExtension(c, uri)) {
236        return readStringExtension(c, uri);
237      }
238    }
239    return null;
240  }
241
242  public static String readStringExtension(DomainResource c, String uri) {
243    Extension ex = getExtension(c, uri);
244    if (ex == null)
245      return null;
246    if ((ex.getValue() instanceof StringType))
247      return ((StringType) ex.getValue()).getValue();
248    if ((ex.getValue() instanceof UriType))
249      return ((UriType) ex.getValue()).getValue();
250    if (ex.getValue() instanceof CodeType)
251      return ((CodeType) ex.getValue()).getValue();
252    if (ex.getValue() instanceof IntegerType)
253      return ((IntegerType) ex.getValue()).asStringValue();
254    if (ex.getValue() instanceof Integer64Type)
255      return ((Integer64Type) ex.getValue()).asStringValue();
256    if (ex.getValue() instanceof DecimalType)
257      return ((DecimalType) ex.getValue()).asStringValue();
258    if ((ex.getValue() instanceof MarkdownType))
259      return ((MarkdownType) ex.getValue()).getValue();
260    return null;
261  }
262
263  public static String readStringSubExtension(DomainResource c, String uri, String name) {
264    Extension ex = getExtension(c, uri);
265    if (ex == null)
266      return null;
267    ex = getExtension(ex, name);
268    if (ex == null)
269      return null;
270    if ((ex.getValue() instanceof StringType))
271      return ((StringType) ex.getValue()).getValue();
272    if ((ex.getValue() instanceof UriType))
273      return ((UriType) ex.getValue()).getValue();
274    if (ex.getValue() instanceof CodeType)
275      return ((CodeType) ex.getValue()).getValue();
276    if (ex.getValue() instanceof IntegerType)
277      return ((IntegerType) ex.getValue()).asStringValue();
278    if (ex.getValue() instanceof Integer64Type)
279      return ((Integer64Type) ex.getValue()).asStringValue();
280    if (ex.getValue() instanceof DecimalType)
281      return ((DecimalType) ex.getValue()).asStringValue();
282    if ((ex.getValue() instanceof MarkdownType))
283      return ((MarkdownType) ex.getValue()).getValue();
284    return null;
285  }
286
287  @SuppressWarnings("unchecked")
288  public static PrimitiveType<DataType> readPrimitiveExtension(DomainResource c, String uri) {
289    Extension ex = getExtension(c, uri);
290    if (ex == null)
291      return null;
292    return (PrimitiveType<DataType>) ex.getValue();
293  }
294
295  public static boolean findStringExtension(Element c, String uri) {
296    Extension ex = ExtensionHelper.getExtension(c, uri);
297    if (ex == null)
298      return false;
299    if (!(ex.getValue() instanceof StringType))
300      return false;
301    return !StringUtils.isBlank(((StringType) ex.getValue()).getValue());
302  }
303
304  public static Boolean readBooleanExtension(Element c, String uri) {
305    Extension ex = ExtensionHelper.getExtension(c, uri);
306    if (ex == null)
307      return null;
308    if (!(ex.getValue() instanceof BooleanType))
309      return null;
310    return ((BooleanType) ex.getValue()).getValue();
311  }
312
313  public static boolean findBooleanExtension(Element c, String uri) {
314    Extension ex = ExtensionHelper.getExtension(c, uri);
315    if (ex == null)
316      return false;
317    if (!(ex.getValue() instanceof BooleanType))
318      return false;
319    return true;
320  }
321
322  public static Boolean readBooleanExtension(DomainResource c, String uri) {
323    Extension ex = ExtensionHelper.getExtension(c, uri);
324    if (ex == null)
325      return null;
326    if (!(ex.getValue() instanceof BooleanType))
327      return null;
328    return ((BooleanType) ex.getValue()).getValue();
329  }
330
331  public static boolean readBoolExtension(DomainResource c, String uri) {
332    Extension ex = ExtensionHelper.getExtension(c, uri);
333    if (ex == null)
334      return false;
335    if (!(ex.getValue() instanceof BooleanType))
336      return false;
337    return ((BooleanType) ex.getValue()).getValue();
338  }
339
340  public static boolean readBoolExtension(DomainResource c, String... uris) {
341    Extension ex = null;
342    for (String uri : uris) {
343      ex = ExtensionHelper.getExtension(c, uri);
344      if (ex != null) {
345        break;
346      }
347    }
348    if (ex == null)
349      return false;
350    if (!(ex.getValue() instanceof BooleanType))
351      return false;
352    return ((BooleanType) ex.getValue()).getValue();
353  }
354
355  public static boolean readBoolExtension(Element e, String uri) {
356    Extension ex = ExtensionHelper.getExtension(e, uri);
357    if (ex == null)
358      return false;
359    if (!(ex.getValue() instanceof BooleanType))
360      return false;
361    if (!(ex.getValue().hasPrimitiveValue()))
362      return false;
363    return ((BooleanType) ex.getValue()).getValue();
364  }
365
366  public static boolean findBooleanExtension(DomainResource c, String uri) {
367    Extension ex = ExtensionHelper.getExtension(c, uri);
368    if (ex == null)
369      return false;
370    if (!(ex.getValue() instanceof BooleanType))
371      return false;
372    return true;
373  }
374
375  public static String getCSComment(CodeSystem.ConceptDefinitionComponent c) {
376    return readStringExtension(c, ExtensionDefinitions.EXT_CS_COMMENT);
377  }
378  //
379  //  public static Boolean getDeprecated(Element c) {
380  //    return readBooleanExtension(c, EXT_DEPRECATED);
381  //  }
382
383  public static boolean hasCSComment(CodeSystem.ConceptDefinitionComponent c) {
384    return findStringExtension(c, ExtensionDefinitions.EXT_CS_COMMENT);
385  }
386
387  //  public static boolean hasDeprecated(Element c) {
388  //    return findBooleanExtension(c, EXT_DEPRECATED);
389  //  }
390
391  public static void addFlyOver(Questionnaire.QuestionnaireItemComponent item, String text, String linkId){
392    if (!StringUtils.isBlank(text)) {
393      Questionnaire.QuestionnaireItemComponent display = item.addItem();
394      display.setType(Questionnaire.QuestionnaireItemType.DISPLAY);
395      display.setText(text);
396      display.setLinkId(linkId);
397      display.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_CONTROL, Factory.newCodeableConcept("flyover", "http://hl7.org/fhir/questionnaire-item-control", "Fly-over"), true));
398    }
399  }
400
401  public static void addMin(Questionnaire.QuestionnaireItemComponent item, int min) {
402    item.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_MINOCCURS, Factory.newInteger(min), true));
403  }
404
405  public static void addMax(Questionnaire.QuestionnaireItemComponent item, int max) {
406    item.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_MAXOCCURS, Factory.newInteger(max), true));
407  }
408
409  public static void addFhirType(Questionnaire.QuestionnaireItemComponent group, String value) {
410    group.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_FHIRTYPE, Factory.newString_(value), true));
411  }
412
413  public static void addControl(Questionnaire.QuestionnaireItemComponent group, String value) {
414    group.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_CONTROL, Factory.newCodeableConcept(value, "http://hl7.org/fhir/questionnaire-item-control", value), true));
415  }
416
417  public static void addAllowedResource(Questionnaire.QuestionnaireItemComponent group, String value) {
418    group.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_ALLOWEDRESOURCE, Factory.newCode(value), true));
419  }
420
421  public static void addReferenceFilter(Questionnaire.QuestionnaireItemComponent group, String value) {
422    group.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_REFERENCEFILTER, Factory.newString_(value), true));
423  }
424
425  //  public static void addIdentifier(Element element, Identifier value) {
426  //    element.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_IDENTIFIER, value, true));
427  //  }
428
429  /**
430   * @param name the identity of the extension of interest
431   * @return The extension, if on this element, else null
432   */
433  public static Extension getExtension(DomainResource resource, String name) {
434    if (resource == null || name == null)
435      return null;
436    if (!resource.hasExtension())
437      return null;
438    for (Extension e : resource.getExtension()) {
439      if (name.equals(e.getUrl()))
440        return e;
441    }
442    return null;
443  }
444
445  public static Extension getExtension(Element el, String name) {
446    if (name == null)
447      return null;
448    if (!el.hasExtension())
449      return null;
450    for (Extension e : el.getExtension()) {
451      if (name.equals(e.getUrl()))
452        return e;
453    }
454    return null;
455  }
456
457  public static void setStringExtension(DomainResource resource, String uri, String value) {
458    if (Utilities.noString(value))
459      return;
460    Extension ext = getExtension(resource, uri);
461    if (ext != null)
462      ext.setValue(new StringType(value));
463    else
464      resource.getExtension().add(new Extension(uri).setValue(new StringType(value)));
465  }
466
467  public static void setStringExtension(Element resource, String uri, String value) {
468    if (Utilities.noString(value))
469      return;
470    Extension ext = getExtension(resource, uri);
471    if (ext != null)
472      ext.setValue(new StringType(value));
473    else
474      resource.getExtension().add(new Extension(uri).setValue(new StringType(value)));
475  }
476
477  public static void setUriExtension(DomainResource resource, String uri, String value) {
478    if (Utilities.noString(value))
479      return;
480    Extension ext = getExtension(resource, uri);
481    if (ext != null)
482      ext.setValue(new UriType(value));
483    else
484      resource.getExtension().add(new Extension(uri).setValue(new UriType(value)));
485  }
486
487  public static void setUriExtension(Element resource, String uri, String value) {
488    if (Utilities.noString(value))
489      return;
490    Extension ext = getExtension(resource, uri);
491    if (ext != null)
492      ext.setValue(new UriType(value));
493    else
494      resource.getExtension().add(new Extension(uri).setValue(new UriType(value)));
495  }
496
497  public static void setCanonicalExtension(DomainResource resource, String uri, String value) {
498    if (Utilities.noString(value))
499      return;
500    Extension ext = getExtension(resource, uri);
501    if (ext != null)
502      ext.setValue(new UriType(value));
503    else
504      resource.getExtension().add(new Extension(uri).setValue(new CanonicalType(value)));
505  }
506
507  public static void setCanonicalExtension(Element resource, String uri, String value) {
508    if (Utilities.noString(value))
509      return;
510    Extension ext = getExtension(resource, uri);
511    if (ext != null)
512      ext.setValue(new UriType(value));
513    else
514      resource.getExtension().add(new Extension(uri).setValue(new CanonicalType(value)));
515  }
516
517  public static void setUrlExtension(DomainResource resource, String uri, String value) {
518    if (Utilities.noString(value))
519      return;
520    Extension ext = getExtension(resource, uri);
521    if (ext != null)
522      ext.setValue(new UrlType(value));
523    else
524      resource.getExtension().add(new Extension(uri).setValue(new UrlType(value)));
525  }
526
527  public static void setUrlExtension(Element resource, String uri, String value) {
528    if (Utilities.noString(value))
529      return;
530    Extension ext = getExtension(resource, uri);
531    if (ext != null)
532      ext.setValue(new UrlType(value));
533    else
534      resource.getExtension().add(new Extension(uri).setValue(new UrlType(value)));
535  }
536
537  public static void setCodeExtension(DomainResource resource, String uri, String value) {
538    if (Utilities.noString(value))
539      return;
540
541    Extension ext = getExtension(resource, uri);
542    if (ext != null)
543      ext.setValue(new CodeType(value));
544    else
545      resource.getExtension().add(new Extension(uri).setValue(new CodeType(value)));
546  }
547
548  public static void setCodeExtensionMod(DomainResource resource, String uri, String value) {
549    if (Utilities.noString(value))
550      return;
551
552    Extension ext = getExtension(resource, uri);
553    if (ext != null)
554      ext.setValue(new CodeType(value));
555    else
556      resource.getModifierExtension().add(new Extension(uri).setValue(new CodeType(value)));
557  }
558
559  public static void setCodeExtensionMod(BackboneElement resource, String uri, String value) {
560    if (Utilities.noString(value))
561      return;
562
563    Extension ext = getExtension(resource, uri);
564    if (ext != null)
565      ext.setValue(new CodeType(value));
566    else
567      resource.getModifierExtension().add(new Extension(uri).setValue(new CodeType(value)));
568  }
569
570  public static void setCodeExtension(Element element, String uri, String value) {
571    if (Utilities.noString(value))
572      return;
573
574    Extension ext = getExtension(element, uri);
575    if (ext != null)
576      ext.setValue(new CodeType(value));
577    else
578      element.getExtension().add(new Extension(uri).setValue(new CodeType(value)));
579  }
580
581  public static void setMarkdownExtension(DomainResource resource, String uri, String value) {
582    if (Utilities.noString(value))
583      return;
584
585    Extension ext = getExtension(resource, uri);
586    if (ext != null)
587      ext.setValue(new MarkdownType(value));
588    else
589      resource.getExtension().add(new Extension(uri).setValue(new MarkdownType(value)));
590  }
591
592  public static void setIntegerExtension(DomainResource resource, String uri, int value) {
593    Extension ext = getExtension(resource, uri);
594    if (ext != null)
595      ext.setValue(new IntegerType(value));
596    else
597      resource.getExtension().add(new Extension(uri).setValue(new IntegerType(value)));
598  }
599
600  //  public static String getOID(CodeSystem define) {
601  //    return readStringExtension(define, EXT_OID);
602  //  }
603  //
604  //  public static String getOID(ValueSet vs) {
605  //    return readStringExtension(vs, EXT_OID);
606  //  }
607  //
608  //  public static void setOID(CodeSystem define, String oid) throws FHIRFormatError, URISyntaxException {
609  //    if (!oid.startsWith("urn:oid:"))
610  //      throw new FHIRFormatError("Error in OID format");
611  //    if (oid.startsWith("urn:oid:urn:oid:"))
612  //      throw new FHIRFormatError("Error in OID format");
613  //    if (!hasExtension(define, EXT_OID))
614  //    define.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_OID, Factory.newUri(oid), false));
615  //    else if (!oid.equals(readStringExtension(define, EXT_OID)))
616  //      throw new Error("Attempt to assign multiple OIDs to a code system");
617  //  }
618  //  public static void setOID(ValueSet vs, String oid) throws FHIRFormatError, URISyntaxException {
619  //    if (!oid.startsWith("urn:oid:"))
620  //      throw new FHIRFormatError("Error in OID format");
621  //    if (oid.startsWith("urn:oid:urn:oid:"))
622  //      throw new FHIRFormatError("Error in OID format");
623  //    if (!hasExtension(vs, EXT_OID))
624  //    vs.getExtension().add(Factory.newExtension(ExtensionDefinitions.EXT_OID, Factory.newUri(oid), false));
625  //    else if (!oid.equals(readStringExtension(vs, EXT_OID)))
626  //      throw new Error("Attempt to assign multiple OIDs to value set "+vs.getName()+" ("+vs.getUrl()+"). Has "+readStringExtension(vs, EXT_OID)+", trying to add "+oid);
627  //  }
628
629  public static boolean hasLanguageTranslations(Element element) {
630    for (Extension e : element.getExtension()) {
631      if (e.getUrl().equals(ExtensionDefinitions.EXT_TRANSLATION)) {
632        return true;
633      }
634    }
635    return false;
636  }
637
638  public static boolean hasLanguageTranslation(Element element, String lang) {
639    for (Extension e : element.getExtension()) {
640      if (e.getUrl().equals(ExtensionDefinitions.EXT_TRANSLATION)) {
641        Extension e1 = ExtensionHelper.getExtension(e, "lang");
642
643        if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang))
644          return true;
645      }
646    }
647    return false;
648  }
649
650  public static String getLanguageTranslation(Element element, String lang) {
651    for (Extension e : element.getExtension()) {
652      if (e.getUrl().equals(ExtensionDefinitions.EXT_TRANSLATION)) {
653        Extension e1 = ExtensionHelper.getExtension(e, "lang");
654
655        if (e1 != null && e1.getValue() != null && e1.getValue() instanceof CodeType && ((CodeType) e1.getValue()).getValue().equals(lang)) {
656          e1 = ExtensionHelper.getExtension(e, "content");
657          if (e1 != null && e1.hasValue()) {
658            return e1.getValue().primitiveValue();
659          }
660        }
661      }
662    }
663    return null;
664  }
665
666  public static StringType getLanguageTranslationElement(Element element, String lang) {
667    for (Extension e : element.getExtension()) {
668      if (e.getUrl().equals(ExtensionDefinitions.EXT_TRANSLATION)) {
669        Extension e1 = ExtensionHelper.getExtension(e, "lang");
670
671        if (e1 != null && e1.getValue() != null && e1.getValue() instanceof CodeType && ((CodeType) e1.getValue()).getValue().equals(lang)) {
672          e1 = ExtensionHelper.getExtension(e, "content");
673          return ((StringType) e1.getValue());
674        }
675      }
676    }
677    return null;
678  }
679
680  public static void addLanguageTranslation(Element element, String lang, String value) {
681    if (Utilities.noString(lang) || Utilities.noString(value))
682      return;
683
684    Extension extension = new Extension().setUrl(ExtensionDefinitions.EXT_TRANSLATION);
685    extension.addExtension().setUrl("lang").setValue(new CodeType(lang));
686    extension.addExtension().setUrl("content").setValue(new StringType(value));
687    element.getExtension().add(extension);
688  }
689
690  public static void setLanguageTranslation(Element element, String lang, String value) {
691    if (Utilities.noString(lang) || Utilities.noString(value))
692      return;
693
694    for (Extension extension : element.getExtension()) {
695      if (ExtensionDefinitions.EXT_TRANSLATION.equals(extension.getUrl())) {
696        String l = extension.getExtensionString("lang");
697        if (lang.equals(l)) {
698          setStringExtension(extension, "content", value);
699          return;
700        }
701      }
702    }
703
704    Extension extension = new Extension().setUrl(ExtensionDefinitions.EXT_TRANSLATION);
705    extension.addExtension().setUrl("lang").setValue(new CodeType(lang));
706    extension.addExtension().setUrl("content").setValue(new StringType(value));
707    element.getExtension().add(extension);
708  }
709
710  public static boolean hasAllowedUnits(ElementDefinition eld) {
711    for (Extension e : eld.getExtension())
712      if (e.getUrl().equals(ExtensionDefinitions.EXT_ALLOWABLE_UNITS))
713        return true;
714    return false;
715  }
716
717  public static DataType getAllowedUnits(ElementDefinition eld) {
718    for (Extension e : eld.getExtension())
719      if (e.getUrl().equals(ExtensionDefinitions.EXT_ALLOWABLE_UNITS))
720        return e.getValue();
721    return null;
722  }
723
724  public static void setAllowableUnits(ElementDefinition eld, CodeableConcept cc) {
725    for (Extension e : eld.getExtension())
726      if (e.getUrl().equals(ExtensionDefinitions.EXT_ALLOWABLE_UNITS)) {
727        e.setValue(cc);
728        return;
729      }
730    eld.getExtension().add(new Extension().setUrl(ExtensionDefinitions.EXT_ALLOWABLE_UNITS).setValue(cc));
731  }
732
733  public static List<Extension> getExtensions(Element element, String url) {
734    List<Extension> results = new ArrayList<Extension>();
735    for (Extension ex : element.getExtension())
736      if (ex.getUrl().equals(url))
737        results.add(ex);
738    return results;
739  }
740
741  public static List<Extension> getExtensions(DomainResource resource, String url) {
742    List<Extension> results = new ArrayList<Extension>();
743    for (Extension ex : resource.getExtension())
744      if (ex.getUrl().equals(url))
745        results.add(ex);
746    return results;
747  }
748
749  //  public static void addDEReference(DataElement de, String value) {
750  //    for (Extension e : de.getExtension())
751  //      if (e.getUrl().equals(ExtensionDefinitions.EXT_CIMI_REFERENCE)) {
752  //        e.setValue(new UriType(value));
753  //        return;
754  //      }
755  //    de.getExtension().add(new Extension().setUrl(ExtensionDefinitions.EXT_CIMI_REFERENCE).setValue(new UriType(value)));
756  //  }
757
758  //  public static void setDeprecated(Element nc) {
759  //    for (Extension e : nc.getExtension())
760  //      if (e.getUrl().equals(ExtensionDefinitions.EXT_DEPRECATED)) {
761  //        e.setValue(new BooleanType(true));
762  //        return;
763  //      }
764  //    nc.getExtension().add(new Extension().setUrl(ExtensionDefinitions.EXT_DEPRECATED).setValue(new BooleanType(true)));
765  //  }
766
767  public static void setExtension(Element focus, String url, Coding c) {
768    for (Extension e : focus.getExtension())
769      if (e.getUrl().equals(url)) {
770        e.setValue(c);
771        return;
772      }
773    focus.getExtension().add(new Extension().setUrl(url).setValue(c));
774  }
775
776  public static void removeExtension(DomainResource focus, String url) {
777    Iterator<Extension> i = focus.getExtension().iterator();
778    while (i.hasNext()) {
779      Extension e = i.next(); // must be called before you can call i.remove()
780      if (url.equals(e.getUrl())) {
781        i.remove();
782      }
783    }
784  }
785
786  public static void removeExtension(Element focus, String url) {
787    Iterator<Extension> i = focus.getExtension().iterator();
788    while (i.hasNext()) {
789      Extension e = i.next(); // must be called before you can call i.remove()
790      if (e.getUrl().equals(url)) {
791        i.remove();
792      }
793    }
794  }
795
796  public static int readIntegerExtension(DomainResource dr, String uri, int defaultValue) {
797    Extension ex = ExtensionHelper.getExtension(dr, uri);
798    if (ex == null)
799      return defaultValue;
800    if (ex.getValue() instanceof IntegerType)
801      return ((IntegerType) ex.getValue()).getValue();
802    throw new Error("Unable to read extension "+uri+" as an integer");
803  }
804
805  public static int readIntegerExtension(Element e, String uri, int defaultValue) {
806    Extension ex = ExtensionHelper.getExtension(e, uri);
807    if (ex == null)
808      return defaultValue;
809    if (ex.getValue() instanceof IntegerType)
810      return ((IntegerType) ex.getValue()).getValue();
811    if (ex.getValue() instanceof DecimalType)
812      return ((DecimalType) ex.getValue()).getValue().intValue();
813    throw new Error("Unable to read extension "+uri+" as an integer");
814  }
815
816  public static Map<String, String> getLanguageTranslations(Element e) {
817    Map<String, String> res = new HashMap<String, String>();
818    for (Extension ext : e.getExtension()) {
819      if (ext.getUrl().equals(ExtensionDefinitions.EXT_TRANSLATION)) {
820        String lang = readStringExtension(ext, "lang");
821        String value = readStringExtension(ext, "content");
822        res.put(lang,  value);
823      }
824    }
825    return res;
826  }
827
828  public static StandardsStatus getStandardsStatus(DomainResource dr) throws FHIRException {
829    return StandardsStatus.fromCode(ExtensionUtilities.readStringExtension(dr, ExtensionDefinitions.EXT_STANDARDS_STATUS));
830  }
831
832  public static StandardsStatus getStandardsStatus(Element e) throws FHIRException {
833    return StandardsStatus.fromCode(ExtensionUtilities.readStringExtension(e, ExtensionDefinitions.EXT_STANDARDS_STATUS));
834  }
835
836  public static void setStandardsStatus(DomainResource dr, StandardsStatus status, String normativeVersion) {
837    if (status == null)
838      ExtensionUtilities.removeExtension(dr, ExtensionDefinitions.EXT_STANDARDS_STATUS);
839    else
840      ExtensionUtilities.setCodeExtension(dr, ExtensionDefinitions.EXT_STANDARDS_STATUS, status.toCode());
841    if (normativeVersion == null)
842      ExtensionUtilities.removeExtension(dr, ExtensionDefinitions.EXT_NORMATIVE_VERSION);
843    else
844      ExtensionUtilities.setCodeExtension(dr, ExtensionDefinitions.EXT_NORMATIVE_VERSION, normativeVersion);
845  }
846
847  public static void setStandardsStatus(Element dr, StandardsStatus status, String normativeVersion) {
848    if (status == null)
849      ExtensionUtilities.removeExtension(dr, ExtensionDefinitions.EXT_STANDARDS_STATUS);
850    else
851      ExtensionUtilities.setCodeExtension(dr, ExtensionDefinitions.EXT_STANDARDS_STATUS, status.toCode());
852    if (normativeVersion == null)
853      ExtensionUtilities.removeExtension(dr, ExtensionDefinitions.EXT_NORMATIVE_VERSION);
854    else
855      ExtensionUtilities.setCodeExtension(dr, ExtensionDefinitions.EXT_NORMATIVE_VERSION, normativeVersion);
856  }
857
858  public static ValidationMessage readValidationMessage(OperationOutcome.OperationOutcomeIssueComponent issue, ValidationMessage.Source source) {
859    ValidationMessage vm = new ValidationMessage();
860    vm.setSource(source);
861    vm.setLevel(mapSeverity(issue.getSeverity()));
862    vm.setType(mapType(issue.getCode()));
863    if (issue.hasExtension(ExtensionDefinitions.EXT_ISSUE_LINE))
864      vm.setLine(ExtensionUtilities.readIntegerExtension(issue, ExtensionDefinitions.EXT_ISSUE_LINE, 0));
865    if (issue.hasExtension(ExtensionDefinitions.EXT_ISSUE_COL))
866      vm.setCol(ExtensionUtilities.readIntegerExtension(issue, ExtensionDefinitions.EXT_ISSUE_COL, 0));
867    if (issue.hasExpression())
868      vm.setLocation(issue.getExpression().get(0).asStringValue());
869    vm.setMessage(issue.getDetails().getText());
870    if (issue.hasExtension("http://hl7.org/fhir/StructureDefinition/rendering-xhtml"))
871      vm.setHtml(ExtensionUtilities.readStringExtension(issue, "http://hl7.org/fhir/StructureDefinition/rendering-xhtml"));
872    return vm;
873  }
874
875  private static ValidationMessage.IssueType mapType(org.hl7.fhir.r5.model.OperationOutcome.IssueType code) {
876    if (code == null) {
877      return null;
878    }
879    switch (code) {
880      case BUSINESSRULE: return ValidationMessage.IssueType.BUSINESSRULE;
881      case CODEINVALID: return ValidationMessage.IssueType.CODEINVALID;
882      case CONFLICT: return ValidationMessage.IssueType.CONFLICT;
883      case DELETED: return ValidationMessage.IssueType.DELETED;
884      case DUPLICATE: return ValidationMessage.IssueType.DUPLICATE;
885      case EXCEPTION: return ValidationMessage.IssueType.EXCEPTION;
886      case EXPIRED: return ValidationMessage.IssueType.EXPIRED;
887      case EXTENSION: return ValidationMessage.IssueType.EXTENSION;
888      case FORBIDDEN: return ValidationMessage.IssueType.FORBIDDEN;
889      case INCOMPLETE: return ValidationMessage.IssueType.INCOMPLETE;
890      case INFORMATIONAL: return ValidationMessage.IssueType.INFORMATIONAL;
891      case INVALID: return ValidationMessage.IssueType.INVALID;
892      case INVARIANT: return ValidationMessage.IssueType.INVARIANT;
893      case LOCKERROR: return ValidationMessage.IssueType.LOCKERROR;
894      case LOGIN: return ValidationMessage.IssueType.LOGIN;
895      case MULTIPLEMATCHES: return ValidationMessage.IssueType.MULTIPLEMATCHES;
896      case NOSTORE: return ValidationMessage.IssueType.NOSTORE;
897      case NOTFOUND: return ValidationMessage.IssueType.NOTFOUND;
898      case NOTSUPPORTED: return ValidationMessage.IssueType.NOTSUPPORTED;
899      case NULL: return ValidationMessage.IssueType.NULL;
900      case PROCESSING: return ValidationMessage.IssueType.PROCESSING;
901      case REQUIRED: return ValidationMessage.IssueType.REQUIRED;
902      case SECURITY: return ValidationMessage.IssueType.SECURITY;
903      case STRUCTURE: return ValidationMessage.IssueType.STRUCTURE;
904      case SUPPRESSED: return ValidationMessage.IssueType.SUPPRESSED;
905      case THROTTLED: return ValidationMessage.IssueType.THROTTLED;
906      case TIMEOUT: return ValidationMessage.IssueType.TIMEOUT;
907      case TOOCOSTLY: return ValidationMessage.IssueType.TOOCOSTLY;
908      case TOOLONG: return ValidationMessage.IssueType.TOOLONG;
909      case TRANSIENT: return ValidationMessage.IssueType.TRANSIENT;
910      case UNKNOWN: return ValidationMessage.IssueType.UNKNOWN;
911      case VALUE: return ValidationMessage.IssueType.VALUE;
912      default: return null;
913    }
914  }
915
916  private static ValidationMessage.IssueSeverity mapSeverity(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity severity) {
917    if (severity == null) {
918      return null;
919    }
920    switch (severity) {
921      case ERROR: return ValidationMessage.IssueSeverity.ERROR;
922      case FATAL: return ValidationMessage.IssueSeverity.FATAL;
923      case INFORMATION: return ValidationMessage.IssueSeverity.INFORMATION;
924      case WARNING: return ValidationMessage.IssueSeverity.WARNING;
925      default: return null;
926    }
927  }
928
929  public static String getPresentation(PrimitiveType<?> type) {
930    if (type.hasExtension(ExtensionDefinitions.EXT_RENDERED_VALUE))
931      return readStringExtension(type, ExtensionDefinitions.EXT_RENDERED_VALUE);
932    return type.primitiveValue();
933  }
934
935  public static String getPresentation(Element holder, PrimitiveType<?> type) {
936    if (holder.hasExtension(ExtensionDefinitions.EXT_RENDERED_VALUE))
937      return readStringExtension(holder, ExtensionDefinitions.EXT_RENDERED_VALUE);
938    if (type.hasExtension(ExtensionDefinitions.EXT_RENDERED_VALUE))
939      return readStringExtension(type, ExtensionDefinitions.EXT_RENDERED_VALUE);
940    return type.primitiveValue();
941  }
942
943  //  public static boolean hasOID(ValueSet vs) {
944  //    return hasExtension(vs, EXT_OID);
945  //  }
946  //
947  //  public static boolean hasOID(CodeSystem cs) {
948  //    return hasExtension(cs, EXT_OID);
949  //  }
950  //
951  public static void addUrlExtension(Element e, String url, String content) {
952    if (!StringUtils.isBlank(content)) {
953      Extension ex = getExtension(e, url);
954      if (ex != null)
955        ex.setValue(new UrlType(content));
956      else
957        e.getExtension().add(Factory.newExtension(url, new UrlType(content), true));
958    }
959  }
960
961  public static void addUrlExtension(DomainResource dr, String url, String value) {
962    Extension ex = getExtension(dr, url);
963    if (ex != null)
964      ex.setValue(new UrlType(value));
965    else
966      dr.getExtension().add(Factory.newExtension(url, new UrlType(value), true));
967  }
968
969  public static void addUriExtension(Element e, String url, String content) {
970    if (!StringUtils.isBlank(content)) {
971      Extension ex = getExtension(e, url);
972      if (ex != null)
973        ex.setValue(new UriType(content));
974      else
975        e.getExtension().add(Factory.newExtension(url, new UriType(content), true));
976    }
977  }
978
979  public static void addUriExtension(DomainResource dr, String url, String value) {
980    Extension ex = getExtension(dr, url);
981    if (ex != null)
982      ex.setValue(new UriType(value));
983    else
984      dr.getExtension().add(Factory.newExtension(url, new UriType(value), true));
985  }
986
987  public static boolean usesExtension(String url, Base base) {
988    if ("Extension".equals(base.fhirType())) {
989      Property p = base.getNamedProperty("url");
990      for (Base b : p.getValues()) {
991        if (url.equals(b.primitiveValue())) {
992          return true;
993        }
994      }
995    }
996
997    for (Property p : base.children() ) {
998      for (Base v : p.getValues()) {
999        if (usesExtension(url, v)) {
1000          return true;
1001        }
1002      }
1003    }
1004    return false;
1005  }
1006
1007  private static Set<String> cachedConsts;
1008
1009  public static Set<String> allConsts() {
1010    if (cachedConsts == null) {
1011      Set<String> list = new HashSet<>();
1012      for (Field field : ExtensionUtilities.class.getDeclaredFields()) {
1013        int modifiers = field.getModifiers();
1014        if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
1015          try {
1016            list.add(field.get(field.getType()).toString());
1017          } catch (Exception e) {
1018          }
1019        }
1020      }
1021      cachedConsts = list;
1022    }
1023    return cachedConsts;
1024  }
1025
1026  public static boolean hasAnyOfExtensions(Element d, String... urls) {
1027    for (String url : urls) {
1028      if (d.hasExtension(url)) {
1029        return true;
1030      }
1031    }
1032    return false;
1033  }
1034
1035  public static boolean hasAnyOfExtensions(DomainResource dr, String... urls) {
1036    for (String url : urls) {
1037      if (dr.hasExtension(url)) {
1038        return true;
1039      }
1040    }
1041    return false;
1042  }
1043
1044  public static int countExtensions(ElementDefinition d, String... urls) {
1045    int res = 0;
1046    for (String url : urls) {
1047      if (d.hasExtension(url)) {
1048        res++;
1049      }
1050    }
1051    return res;
1052  }
1053
1054  public static boolean hasExtensionValue(StructureDefinition src, String url, String value) {
1055    for (Extension ext : src.getExtension()) {
1056      if (url.equals(ext.getUrl()) && ext.hasValue() && value.equals(ext.getValue().primitiveValue())) {
1057        return true;
1058      }
1059    }
1060    return false;
1061  }
1062
1063
1064  private static Extension setExtensionE(Element context, String url, DataType value) {
1065    for (Extension ext : context.getExtension()) {
1066      if (ext.getUrl().equals(url)) {
1067        return ext.setValue(value);
1068      }
1069    }
1070    return context.addExtension().setUrl(url).setValue(value);
1071  }
1072
1073  private static Extension setExtensionBE(BackboneElement context, boolean mod, String url, DataType value) {
1074    if (mod) {
1075      for (Extension ext : context.getModifierExtension()) {
1076        if (ext.getUrl().equals(url)) {
1077          return ext.setValue(value);
1078        }
1079      }
1080      return context.addModifierExtension().setUrl(url).setValue(value);
1081    } else {
1082      return setExtensionE(context, url, value);
1083    }
1084  }
1085
1086  private static Extension setExtensionBT(BackboneType context, boolean mod, String url, DataType value) {
1087    if (mod) {
1088      for (Extension ext : context.getModifierExtension()) {
1089        if (ext.getUrl().equals(url)) {
1090          return ext.setValue(value);
1091        }
1092      }
1093      return context.addModifierExtension().setUrl(url).setValue(value);
1094    } else {
1095      return setExtensionE(context, url, value);
1096    }
1097  }
1098
1099  private static Extension setExtensionR(DomainResource context, boolean mod, String url, DataType value) {
1100    if (mod) {
1101      for (Extension ext : context.getModifierExtension()) {
1102        if (ext.getUrl().equals(url)) {
1103          return ext.setValue(value);
1104        }
1105      }
1106      return context.addModifierExtension().setUrl(url).setValue(value);
1107    } else {
1108      for (Extension ext : context.getExtension()) {
1109        if (ext.getUrl().equals(url)) {
1110          return ext.setValue(value);
1111        }
1112      }
1113      return context.addExtension().setUrl(url).setValue(value);
1114    }
1115  }
1116
1117  public static Extension setExtension(Base context, String url, DataType value) {
1118    boolean mod = ExtensionUtilities.isModifier(url);
1119    if (context instanceof BackboneElement) {
1120      return setExtensionBE((BackboneElement) context, mod, url, value);
1121    } else if (mod && context instanceof BackboneType) {
1122      return setExtensionBT((BackboneType) context, mod, url, value);
1123    } else if (context instanceof Element) {
1124      if (mod) {
1125        throw new FHIRException("Can't use a modifier extension on "+context.getClass().getName());
1126      } else {
1127        return setExtensionE((Element) context, url, value);
1128      }
1129    } else if (context instanceof DomainResource) {
1130      return setExtensionR((DomainResource) context, mod, url, value);
1131    } else {
1132      throw new FHIRException("Can't use an extension on "+context.getClass().getName());
1133    }
1134  }
1135
1136
1137  private static Extension addExtensionE(Element context, String url, DataType value) {
1138    return context.addExtension().setValue(value);
1139  }
1140
1141  private static Extension addExtensionBE(BackboneElement context, boolean mod, String url, DataType value) {
1142    if (mod) {
1143      return context.addModifierExtension().setValue(value);
1144    } else {
1145      return setExtensionE(context, url, value);
1146    }
1147  }
1148
1149  private static Extension addExtensionBT(BackboneType context, boolean mod, String url, DataType value) {
1150    if (mod) {
1151      return context.addModifierExtension().setUrl(url).setValue(value);
1152    } else {
1153      return setExtensionE(context, url, value);
1154    }
1155  }
1156
1157  private static Extension addExtensionR(DomainResource context, boolean mod, String url, DataType value) {
1158    if (mod) {
1159      return context.addModifierExtension().setUrl(url).setValue(value);
1160    } else {
1161      return context.addExtension().setUrl(url).setValue(value);
1162    }
1163  }
1164
1165  public static Extension addExtension(Base context, String url, DataType value) {
1166    boolean mod = ExtensionUtilities.isModifier(url);
1167    if (context instanceof BackboneElement) {
1168      return addExtensionBE((BackboneElement) context, mod, url, value);
1169    } else if (mod && context instanceof BackboneType) {
1170      return addExtensionBT((BackboneType) context, mod, url, value);
1171    } else if (context instanceof Element) {
1172      if (mod) {
1173        throw new FHIRException("Can't use a modifier extension on "+context.getClass().getName());
1174      } else {
1175        return addExtensionE((Element) context, url, value);
1176      }
1177    } else if (context instanceof DomainResource) {
1178      return addExtensionR((DomainResource) context, mod, url, value);
1179    } else {
1180      throw new FHIRException("Can't use an extension on "+context.getClass().getName());
1181    }
1182  }
1183
1184  private static List<Extension> getAllExtensions(Base context, String url) {
1185    List<Extension> list = new ArrayList<>();
1186    boolean mod = ExtensionUtilities.isModifier(url);
1187    if (mod) {
1188      if (context instanceof BackboneElement) {
1189        list.addAll(((BackboneElement) context).getModifierExtension());
1190      }
1191      if (context instanceof BackboneType) {
1192        list.addAll(((BackboneElement) context).getModifierExtension());
1193      }
1194      if (context instanceof DomainResource) {
1195        list.addAll(((DomainResource) context).getModifierExtension());
1196      }
1197    } else {
1198      if (context instanceof Element) {
1199        list.addAll(((Element) context).getExtension());
1200      }
1201      if (context instanceof DomainResource) {
1202        list.addAll(((DomainResource) context).getExtension());
1203      }
1204    }
1205    return list;
1206  }
1207
1208  public static <T extends DataType> T getExtension(Class<T> class_, Base context, String url) {
1209    boolean found = false;
1210    T result = null;
1211    for (Extension ext : getAllExtensions(context, url)) {
1212      if (ext.hasUrl() && ext.getUrl().equals(url)) {
1213        if (found) {
1214          throw new FHIRException("Multiple Extensions for "+url);
1215        } else if (ext.hasValue() && class_.isInstance(ext.getValue())) {
1216          found = true;
1217          result = (T) ext.getValue();
1218        }
1219      }
1220    }
1221    return result;
1222  }
1223
1224  public static <T extends DataType> List<T> getExtensionList(Class<T> class_, Base context, String url) {
1225    List<T> result = new ArrayList<>();
1226    for (Extension ext : getAllExtensions(context, url)) {
1227      if (ext.hasUrl() && ext.getUrl().equals(url)) {
1228        if (ext.hasValue() && class_.isInstance(ext.getValue())) {
1229          result.add((T) ext.getValue());
1230        }
1231      }
1232    }
1233    return result;
1234  }
1235
1236  public static String getExtensionString(Base context, String url) {
1237    boolean found = false;
1238    String result = null;
1239    for (Extension ext : getAllExtensions(context, url)) {
1240      if (ext.hasUrl() && ext.getUrl().equals(url)) {
1241        if (found) {
1242          throw new FHIRException("Multiple Extensions for "+url);
1243        } else if (ext.hasValue() && ext.getValue().isPrimitive()) {
1244          found = true;
1245          result = ext.getValue().primitiveValue();
1246        }
1247      }
1248    }
1249    return result;
1250  }
1251
1252  public static Boolean getExtensionBoolean(Base context, String url) {
1253    boolean found = false;
1254    Boolean result = null;
1255    for (Extension ext : getAllExtensions(context, url)) {
1256      if (ext.hasUrl() && ext.getUrl().equals(url)) {
1257        if (found) {
1258          throw new FHIRException("Multiple Extensions for "+url);
1259        } else if (ext.hasValueBooleanType()) {
1260          found = true;
1261          result = ext.getValueBooleanType().getValue();
1262        }
1263      }
1264    }
1265    return result;
1266  }
1267
1268  public static Integer getExtensionInt(Base context, String url) {
1269    boolean found = false;
1270    Integer result = null;
1271    for (Extension ext : getAllExtensions(context, url)) {
1272      if (ext.hasUrl() && ext.getUrl().equals(url)) {
1273        if (found) {
1274          throw new FHIRException("Multiple Extensions for "+url);
1275        } else if (ext.hasValueIntegerType()) {
1276          found = true;
1277          result = ext.getValueIntegerType().getValue();
1278        }
1279      }
1280    }
1281    return result;
1282  }
1283
1284  public static BigDecimal getExtensionFloat(Base context, String url) {
1285    boolean found = false;
1286    BigDecimal result = null;
1287    for (Extension ext : getAllExtensions(context, url)) {
1288      if (ext.hasUrl() && ext.getUrl().equals(url)) {
1289        if (found) {
1290          throw new FHIRException("Multiple Extensions for "+url);
1291        } else if (ext.hasValueIntegerType()) {
1292          found = true;
1293          result = ext.getValueDecimalType().getValue();
1294        }
1295      }
1296    }
1297    return result;
1298  }
1299
1300  public static List<String> getExtensionStringList(Base context, String url) {
1301    List<String> result = new ArrayList<>();
1302    for (Extension ext : getAllExtensions(context, url)) {
1303      if (ext.hasUrl() && ext.getUrl().equals(url)) {
1304        if (ext.hasValue() && ext.getValue().isPrimitive()) {
1305          result.add(ext.getValue().primitiveValue());
1306        }
1307      }
1308    }
1309    return result;
1310  }
1311
1312  public static List<Boolean> getExtensionBooleanList(Base context, String url) {
1313    List<Boolean> result = new ArrayList<>();
1314    for (Extension ext : getAllExtensions(context, url)) {
1315      if (ext.hasUrl() && ext.getUrl().equals(url)) {
1316        if (ext.hasValue() && ext.getValue().isPrimitive()) {
1317          result.add(Boolean.valueOf(ext.getValue().primitiveValue()));
1318        }
1319      }
1320    }
1321    return result;
1322  }
1323
1324  public static List<Integer> getExtensionIntList(Base context, String url) {
1325    List<Integer> result = new ArrayList<>();
1326    for (Extension ext : getAllExtensions(context, url)) {
1327      if (ext.hasUrl() && ext.getUrl().equals(url)) {
1328        if (ext.hasValueIntegerType()) {
1329          result.add(ext.getValueIntegerType().getValue());
1330        }
1331      }
1332    }
1333    return result;
1334  }
1335
1336  public static boolean stripExtensions(Element element, String... exceptions) {
1337    return stripExtensions(element, Utilities.strings(exceptions));
1338  }
1339
1340  public static boolean stripExtensions(Element element, List<String> exceptions) {
1341    boolean res = element.getExtension().removeIf(ex -> !exceptions.contains(ex.getUrl()));
1342    if (element instanceof BackboneElement) {
1343      res = ((BackboneElement) element).getModifierExtension().removeIf(ex -> !exceptions.contains(ex.getUrl())) || res;
1344    }
1345    if (element instanceof BackboneElement) {
1346      res = ((BackboneElement) element).getModifierExtension().removeIf(ex -> !exceptions.contains(ex.getUrl())) || res;
1347    }
1348    for (Property p : element.children()) {
1349      for (Base v : p.getValues()) {
1350        if (v instanceof Element) {
1351          res = stripExtensions((Element) v, exceptions) || res;
1352        } else if (v instanceof Element) {
1353          res = stripExtensions((Resource) v, exceptions) || res;
1354        }
1355      }
1356    }
1357    return res;
1358  }
1359
1360  public static boolean stripExtensions(Resource resource, String... exceptions) {
1361    return stripExtensions(resource, Utilities.strings(exceptions));
1362  }
1363
1364  public static boolean stripExtensions(Resource resource, List<String> exceptions) {
1365    boolean res = false;
1366    if (resource instanceof DomainResource) {
1367      res = ((DomainResource) resource).getExtension().removeIf(ex -> !exceptions.contains(ex.getUrl())) ||
1368        ((DomainResource) resource).getModifierExtension().removeIf(ex -> !exceptions.contains(ex.getUrl()));
1369    }
1370    for (Property p : resource.children()) {
1371      for (Base v : p.getValues()) {
1372        if (v instanceof Element) {
1373          res = stripExtensions((Element) v, exceptions) || res;
1374        } else if (v instanceof Element) {
1375          res = stripExtensions((Resource) v, exceptions) || res;
1376        }
1377      }
1378    }
1379    return res;
1380  }
1381
1382  public static void copyExtensions(List<Extension> source, List<Extension> dest, String... urls) {
1383    if (source != null && dest != null) {
1384      for (Extension ex : source) {
1385        if (Utilities.existsInList(ex.getUrl(), urls)) {
1386          dest.add(ex.copy());
1387        }
1388      }
1389    }
1390  }
1391
1392
1393
1394  public static DataType getExtensionValue(List<Extension> extensions, String url) {
1395    for (Extension ex : extensions) {
1396      if (ex.getUrl().equals(url)) {
1397        return ex.getValue();
1398      }
1399    }
1400    return null;
1401  }
1402
1403
1404  public static String getExtensionString(List<Extension> extensions, String url) {
1405    for (Extension ex : extensions) {
1406      if (ex.getUrl().equals(url)) {
1407        return ex.getValue().primitiveValue();
1408      }
1409    }
1410    return null;
1411  }
1412
1413
1414
1415  public static Integer getExtensionInteger(List<Extension> extensions, String url) {
1416    for (Extension ex : extensions) {
1417      if (ex.getUrl().equals(url) && ex.hasValueIntegerType()) {
1418        return ex.getValueIntegerType().getValue();
1419      }
1420    }
1421    return null;
1422  }
1423
1424  public static boolean hasExtension(List<Extension> extensions, String url) {
1425    if (extensions == null) {
1426      return false;
1427    }
1428    for (Extension ex : extensions) {
1429      if (ex.getUrl().equals(url)) {
1430        return true;
1431      }
1432    }
1433    return false;
1434  }
1435
1436
1437  public static boolean isModifier(String url) {
1438    return Utilities.existsInList(url, "http://hl7.org/fhir/StructureDefinition/artifact-status", "http://hl7.org/fhir/StructureDefinition/capabilitystatement-prohibited", "http://hl7.org/fhir/StructureDefinition/request-doNotPerform");
1439  }
1440
1441}