001package org.hl7.fhir.dstu2.utils;
002
003/*
004  Copyright (c) 2011+, HL7, Inc.
005  All rights reserved.
006  
007  Redistribution and use in source and binary forms, with or without modification, 
008  are permitted provided that the following conditions are met:
009    
010   * Redistributions of source code must retain the above copyright notice, this 
011     list of conditions and the following disclaimer.
012   * Redistributions in binary form must reproduce the above copyright notice, 
013     this list of conditions and the following disclaimer in the documentation 
014     and/or other materials provided with the distribution.
015   * Neither the name of HL7 nor the names of its contributors may be used to 
016     endorse or promote products derived from this software without specific 
017     prior written permission.
018  
019  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
020  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
021  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
022  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
023  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
024  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
025  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
026  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
027  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
028  POSSIBILITY OF SUCH DAMAGE.
029  
030 */
031
032import java.net.URISyntaxException;
033
034/*
035Copyright (c) 2011+, HL7, Inc
036All rights reserved.
037
038Redistribution and use in source and binary forms, with or without modification, 
039are permitted provided that the following conditions are met:
040
041 * Redistributions of source code must retain the above copyright notice, this 
042   list of conditions and the following disclaimer.
043 * Redistributions in binary form must reproduce the above copyright notice, 
044   this list of conditions and the following disclaimer in the documentation 
045   and/or other materials provided with the distribution.
046 * Neither the name of HL7 nor the names of its contributors may be used to 
047   endorse or promote products derived from this software without specific 
048   prior written permission.
049
050THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
051ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
052WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
053IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
054INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
055NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
056PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
057WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
058ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
059POSSIBILITY OF SUCH DAMAGE.
060
061 */
062
063import java.util.ArrayList;
064import java.util.Iterator;
065import java.util.List;
066
067import org.hl7.fhir.dstu2.model.BooleanType;
068import org.hl7.fhir.dstu2.model.CodeType;
069import org.hl7.fhir.dstu2.model.CodeableConcept;
070import org.hl7.fhir.dstu2.model.Coding;
071import org.hl7.fhir.dstu2.model.DataElement;
072import org.hl7.fhir.dstu2.model.DomainResource;
073import org.hl7.fhir.dstu2.model.Element;
074import org.hl7.fhir.dstu2.model.ElementDefinition;
075import org.hl7.fhir.dstu2.model.Extension;
076import org.hl7.fhir.dstu2.model.ExtensionHelper;
077import org.hl7.fhir.dstu2.model.Factory;
078import org.hl7.fhir.dstu2.model.Identifier;
079import org.hl7.fhir.dstu2.model.IntegerType;
080import org.hl7.fhir.dstu2.model.MarkdownType;
081import org.hl7.fhir.dstu2.model.PrimitiveType;
082import org.hl7.fhir.dstu2.model.Questionnaire.GroupComponent;
083import org.hl7.fhir.dstu2.model.Questionnaire.QuestionComponent;
084import org.hl7.fhir.dstu2.model.Reference;
085import org.hl7.fhir.dstu2.model.StringType;
086import org.hl7.fhir.dstu2.model.Type;
087import org.hl7.fhir.dstu2.model.UriType;
088import org.hl7.fhir.dstu2.model.ValueSet;
089import org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent;
090import org.hl7.fhir.dstu2.model.ValueSet.ValueSetCodeSystemComponent;
091import org.hl7.fhir.exceptions.FHIRFormatError;
092import org.hl7.fhir.utilities.Utilities;
093import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
094
095@Deprecated
096public class ToolingExtensions {
097
098  // validated
099  public static final String EXT_SUBSUMES = "http://hl7.org/fhir/StructureDefinition/valueset-subsumes";
100  private static final String EXT_OID = "http://hl7.org/fhir/StructureDefinition/valueset-oid";
101  public static final String EXT_DEPRECATED = "http://hl7.org/fhir/StructureDefinition/valueset-deprecated";
102  public static final String EXT_DEFINITION = "http://hl7.org/fhir/StructureDefinition/valueset-definition";
103  public static final String EXT_COMMENT = "http://hl7.org/fhir/StructureDefinition/valueset-comments";
104  private static final String EXT_IDENTIFIER = "http://hl7.org/fhir/StructureDefinition/identifier";
105  private static final String EXT_TRANSLATION = "http://hl7.org/fhir/StructureDefinition/translation";
106  public static final String EXT_ISSUE_SOURCE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-source";
107  public static final String EXT_DISPLAY_HINT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-display-hint";
108  public static final String EXT_REPLACED_BY = "http://hl7.org/fhir/StructureDefinition/valueset-replacedby";
109  public static final String EXT_JSON_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type";
110  public static final String EXT_XML_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-type";
111  public static final String EXT_REGEX = "http://hl7.org/fhir/StructureDefinition/structuredefinition-regex";
112  public static final String EXT_EXPRESSION = "http://hl7.org/fhir/StructureDefinition/structuredefinition-expression";
113  public static final String EXT_SEARCH_EXPRESSION = "http://hl7.org/fhir/StructureDefinition/searchparameter-expression";
114
115  // unregistered?
116
117  public static final String EXT_FLYOVER = "http://hl7.org/fhir/Profile/questionnaire-extensions#flyover";
118  private static final String EXT_QTYPE = "http://www.healthintersections.com.au/fhir/Profile/metadata#type";
119  private static final String EXT_QREF = "http://www.healthintersections.com.au/fhir/Profile/metadata#reference";
120  private static final String EXTENSION_FILTER_ONLY = "http://www.healthintersections.com.au/fhir/Profile/metadata#expandNeedsFilter";
121  private static final String EXT_TYPE = "http://www.healthintersections.com.au/fhir/Profile/metadata#type";
122  private static final String EXT_REFERENCE = "http://www.healthintersections.com.au/fhir/Profile/metadata#reference";
123  private static final String EXT_ALLOWABLE_UNITS = "http://hl7.org/fhir/StructureDefinition/elementdefinition-allowedUnits";
124  public static final String EXT_CIMI_REFERENCE = "http://hl7.org/fhir/StructureDefinition/cimi-reference";
125  public static final String EXT_UNCLOSED = "http://hl7.org/fhir/StructureDefinition/valueset-unclosed";
126  public static final String EXT_FMM_LEVEL = "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm";
127
128  // specific extension helpers
129
130  public static Extension makeIssueSource(Source source) {
131    Extension ex = new Extension();
132    // todo: write this up and get it published with the pack (and handle the
133    // redirect?)
134    ex.setUrl(ToolingExtensions.EXT_ISSUE_SOURCE);
135    CodeType c = new CodeType();
136    c.setValue(source.toString());
137    ex.setValue(c);
138    return ex;
139  }
140
141  public static boolean hasExtension(DomainResource de, String url) {
142    return getExtension(de, url) != null;
143  }
144
145  public static boolean hasExtension(Element e, String url) {
146    return getExtension(e, url) != null;
147  }
148
149  public static void addStringExtension(DomainResource dr, String url, String content) {
150    if (!Utilities.noString(content)) {
151      Extension ex = getExtension(dr, url);
152      if (ex != null)
153        ex.setValue(new StringType(content));
154      else
155        dr.getExtension().add(Factory.newExtension(url, new StringType(content), true));
156    }
157  }
158
159  public static void addStringExtension(Element e, String url, String content) {
160    if (!Utilities.noString(content)) {
161      Extension ex = getExtension(e, url);
162      if (ex != null)
163        ex.setValue(new StringType(content));
164      else
165        e.getExtension().add(Factory.newExtension(url, new StringType(content), true));
166    }
167  }
168
169  public static void addIntegerExtension(DomainResource dr, String url, int value) {
170    Extension ex = getExtension(dr, url);
171    if (ex != null)
172      ex.setValue(new IntegerType(value));
173    else
174      dr.getExtension().add(Factory.newExtension(url, new IntegerType(value), true));
175  }
176
177  public static void addComment(Element nc, String comment) {
178    if (!Utilities.noString(comment))
179      nc.getExtension().add(Factory.newExtension(EXT_COMMENT, Factory.newString_(comment), true));
180  }
181
182  public static void markDeprecated(Element nc) {
183    setDeprecated(nc);
184  }
185
186  public static void addSubsumes(ConceptDefinitionComponent nc, String code) {
187    nc.getModifierExtension().add(Factory.newExtension(EXT_SUBSUMES, Factory.newCode(code), true));
188  }
189
190  public static void addDefinition(Element nc, String definition) {
191    if (!Utilities.noString(definition))
192      nc.getExtension().add(Factory.newExtension(EXT_DEFINITION, Factory.newString_(definition), true));
193  }
194
195  public static void addDisplayHint(Element def, String hint) {
196    if (!Utilities.noString(hint))
197      def.getExtension().add(Factory.newExtension(EXT_DISPLAY_HINT, Factory.newString_(hint), true));
198  }
199
200  public static String getDisplayHint(Element def) {
201    return readStringExtension(def, EXT_DISPLAY_HINT);
202  }
203
204  public static String readStringExtension(Element c, String uri) {
205    Extension ex = ExtensionHelper.getExtension(c, uri);
206    if (ex == null)
207      return null;
208    if (ex.getValue() instanceof UriType)
209      return ((UriType) ex.getValue()).getValue();
210    if (!(ex.getValue() instanceof StringType))
211      return null;
212    return ((StringType) ex.getValue()).getValue();
213  }
214
215  public static String readStringExtension(DomainResource c, String uri) {
216    Extension ex = getExtension(c, uri);
217    if (ex == null)
218      return null;
219    if ((ex.getValue() instanceof StringType))
220      return ((StringType) ex.getValue()).getValue();
221    if ((ex.getValue() instanceof UriType))
222      return ((UriType) ex.getValue()).getValue();
223    if ((ex.getValue() instanceof MarkdownType))
224      return ((MarkdownType) ex.getValue()).getValue();
225    return null;
226  }
227
228  @SuppressWarnings("unchecked")
229  public static PrimitiveType<Type> readPrimitiveExtension(DomainResource c, String uri) {
230    Extension ex = getExtension(c, uri);
231    if (ex == null)
232      return null;
233    return (PrimitiveType<Type>) ex.getValue();
234  }
235
236  public static boolean findStringExtension(Element c, String uri) {
237    Extension ex = ExtensionHelper.getExtension(c, uri);
238    if (ex == null)
239      return false;
240    if (!(ex.getValue() instanceof StringType))
241      return false;
242    return !Utilities.noString(((StringType) ex.getValue()).getValue());
243  }
244
245  public static Boolean readBooleanExtension(Element c, String uri) {
246    Extension ex = ExtensionHelper.getExtension(c, uri);
247    if (ex == null)
248      return null;
249    if (!(ex.getValue() instanceof BooleanType))
250      return null;
251    return ((BooleanType) ex.getValue()).getValue();
252  }
253
254  public static boolean findBooleanExtension(Element c, String uri) {
255    Extension ex = ExtensionHelper.getExtension(c, uri);
256    if (ex == null)
257      return false;
258    if (!(ex.getValue() instanceof BooleanType))
259      return false;
260    return true;
261  }
262
263  public static String getComment(ConceptDefinitionComponent c) {
264    return readStringExtension(c, EXT_COMMENT);
265  }
266
267  public static Boolean getDeprecated(Element c) {
268    return readBooleanExtension(c, EXT_DEPRECATED);
269  }
270
271  public static boolean hasComment(ConceptDefinitionComponent c) {
272    return findStringExtension(c, EXT_COMMENT);
273  }
274
275  public static boolean hasDeprecated(Element c) {
276    return findBooleanExtension(c, EXT_DEPRECATED);
277  }
278
279  public static List<CodeType> getSubsumes(ConceptDefinitionComponent c) {
280    List<CodeType> res = new ArrayList<CodeType>();
281
282    for (Extension e : c.getExtension()) {
283      if (EXT_SUBSUMES.equals(e.getUrl()))
284        res.add((CodeType) e.getValue());
285    }
286    return res;
287  }
288
289  public static void addFlyOver(GroupComponent group, String text) {
290    if (!Utilities.noString(text))
291      group.getExtension().add(Factory.newExtension(EXT_FLYOVER, Factory.newString_(text), true));
292
293  }
294
295  public static void setQuestionType(GroupComponent group, String text) {
296    if (!Utilities.noString(text))
297      group.getExtension().add(Factory.newExtension(EXT_QTYPE, Factory.newString_(text), true));
298  }
299
300  public static void setQuestionReference(GroupComponent group, String text) {
301    if (!Utilities.noString(text))
302      group.getExtension().add(Factory.newExtension(EXT_QREF, Factory.newString_(text), true));
303  }
304
305  public static void addFlyOver(Element element, String text) {
306    element.getExtension().add(Factory.newExtension(EXT_FLYOVER, Factory.newString_(text), true));
307  }
308
309  public static void addFilterOnly(Reference element, boolean value) {
310    element.getExtension().add(Factory.newExtension(EXTENSION_FILTER_ONLY, Factory.newBoolean(value), true));
311  }
312
313  public static void addType(GroupComponent group, String value) {
314    group.getExtension().add(Factory.newExtension(EXT_TYPE, Factory.newString_(value), true));
315  }
316
317  public static void addReference(QuestionComponent group, String value) {
318    group.getExtension().add(Factory.newExtension(EXT_REFERENCE, Factory.newString_(value), true));
319  }
320
321  public static void addIdentifier(Element element, Identifier value) {
322    element.getExtension().add(Factory.newExtension(EXT_IDENTIFIER, value, true));
323  }
324
325  /**
326   * @param name the identity of the extension of interest
327   * @return The extension, if on this element, else null
328   */
329  public static Extension getExtension(DomainResource resource, String name) {
330    if (name == null)
331      return null;
332    if (!resource.hasExtension())
333      return null;
334    for (Extension e : resource.getExtension()) {
335      if (name.equals(e.getUrl()))
336        return e;
337    }
338    return null;
339  }
340
341  public static Extension getExtension(Element el, String name) {
342    if (name == null)
343      return null;
344    if (!el.hasExtension())
345      return null;
346    for (Extension e : el.getExtension()) {
347      if (name.equals(e.getUrl()))
348        return e;
349    }
350    return null;
351  }
352
353  public static void setStringExtension(DomainResource resource, String uri, String value) {
354    Extension ext = getExtension(resource, uri);
355    if (ext != null)
356      ext.setValue(new StringType(value));
357    else
358      resource.getExtension().add(new Extension(new UriType(uri)).setValue(new StringType(value)));
359  }
360
361  public static String getOID(ValueSetCodeSystemComponent define) {
362    return readStringExtension(define, EXT_OID);
363  }
364
365  public static String getOID(ValueSet vs) {
366    return readStringExtension(vs, EXT_OID);
367  }
368
369  public static void setOID(ValueSetCodeSystemComponent define, String oid) throws FHIRFormatError, URISyntaxException {
370    if (!oid.startsWith("urn:oid:"))
371      throw new FHIRFormatError("Error in OID format");
372    if (oid.startsWith("urn:oid:urn:oid:"))
373      throw new FHIRFormatError("Error in OID format");
374    define.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false));
375  }
376
377  public static void setOID(ValueSet vs, String oid) throws FHIRFormatError, URISyntaxException {
378    if (!oid.startsWith("urn:oid:"))
379      throw new FHIRFormatError("Error in OID format");
380    if (oid.startsWith("urn:oid:urn:oid:"))
381      throw new FHIRFormatError("Error in OID format");
382    vs.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false));
383  }
384
385  public static boolean hasLanguageTranslation(Element element, String lang) {
386    for (Extension e : element.getExtension()) {
387      if (e.getUrl().equals(EXT_TRANSLATION)) {
388        Extension e1 = ExtensionHelper.getExtension(e, "lang");
389
390        if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang))
391          return true;
392      }
393    }
394    return false;
395  }
396
397  public static String getLanguageTranslation(Element element, String lang) {
398    for (Extension e : element.getExtension()) {
399      if (e.getUrl().equals(EXT_TRANSLATION)) {
400        Extension e1 = ExtensionHelper.getExtension(e, "lang");
401
402        if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang)) {
403          e1 = ExtensionHelper.getExtension(e, "content");
404          return ((StringType) e.getValue()).getValue();
405        }
406      }
407    }
408    return null;
409  }
410
411  public static void addLanguageTranslation(Element element, String lang, String value) {
412    Extension extension = new Extension().setUrl(EXT_TRANSLATION);
413    extension.addExtension().setUrl("lang").setValue(new StringType(lang));
414    extension.addExtension().setUrl("content").setValue(new StringType(value));
415    element.getExtension().add(extension);
416  }
417
418  public static Type getAllowedUnits(ElementDefinition eld) {
419    for (Extension e : eld.getExtension())
420      if (e.getUrl().equals(EXT_ALLOWABLE_UNITS))
421        return e.getValue();
422    return null;
423  }
424
425  public static void setAllowableUnits(ElementDefinition eld, CodeableConcept cc) {
426    for (Extension e : eld.getExtension())
427      if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) {
428        e.setValue(cc);
429        return;
430      }
431    eld.getExtension().add(new Extension().setUrl(EXT_ALLOWABLE_UNITS).setValue(cc));
432  }
433
434  public static List<Extension> getExtensions(Element element, String url) {
435    List<Extension> results = new ArrayList<Extension>();
436    for (Extension ex : element.getExtension())
437      if (ex.getUrl().equals(url))
438        results.add(ex);
439    return results;
440  }
441
442  public static List<Extension> getExtensions(DomainResource resource, String url) {
443    List<Extension> results = new ArrayList<Extension>();
444    for (Extension ex : resource.getExtension())
445      if (ex.getUrl().equals(url))
446        results.add(ex);
447    return results;
448  }
449
450  public static void addDEReference(DataElement de, String value) {
451    for (Extension e : de.getExtension())
452      if (e.getUrl().equals(EXT_CIMI_REFERENCE)) {
453        e.setValue(new UriType(value));
454        return;
455      }
456    de.getExtension().add(new Extension().setUrl(EXT_CIMI_REFERENCE).setValue(new UriType(value)));
457  }
458
459  public static void setDeprecated(Element nc) {
460    for (Extension e : nc.getExtension())
461      if (e.getUrl().equals(EXT_DEPRECATED)) {
462        e.setValue(new BooleanType(true));
463        return;
464      }
465    nc.getExtension().add(new Extension().setUrl(EXT_DEPRECATED).setValue(new BooleanType(true)));
466  }
467
468  public static void setExtension(Element focus, String url, Coding c) {
469    for (Extension e : focus.getExtension())
470      if (e.getUrl().equals(url)) {
471        e.setValue(c);
472        return;
473      }
474    focus.getExtension().add(new Extension().setUrl(url).setValue(c));
475  }
476
477  public static void removeExtension(DomainResource focus, String url) {
478    Iterator<Extension> i = focus.getExtension().iterator();
479    while (i.hasNext()) {
480      Extension e = i.next(); // must be called before you can call i.remove()
481      if (e.getUrl().equals(url)) {
482        i.remove();
483      }
484    }
485  }
486
487  public static void removeExtension(Element focus, String url) {
488    Iterator<Extension> i = focus.getExtension().iterator();
489    while (i.hasNext()) {
490      Extension e = i.next(); // must be called before you can call i.remove()
491      if (e.getUrl().equals(url)) {
492        i.remove();
493      }
494    }
495  }
496
497  public static void setStringExtension(Element element, String uri, String value) {
498    Extension ext = getExtension(element, uri);
499    if (ext != null)
500      ext.setValue(new StringType(value));
501    else
502      element.getExtension().add(new Extension(new UriType(uri)).setValue(new StringType(value)));
503  }
504
505}