001package org.hl7.fhir.dstu3.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
032
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.apache.commons.lang3.StringUtils;
068import org.hl7.fhir.dstu3.model.BooleanType;
069import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
070import org.hl7.fhir.dstu3.model.CodeType;
071import org.hl7.fhir.dstu3.model.CodeableConcept;
072import org.hl7.fhir.dstu3.model.Coding;
073import org.hl7.fhir.dstu3.model.DataElement;
074import org.hl7.fhir.dstu3.model.DomainResource;
075import org.hl7.fhir.dstu3.model.Element;
076import org.hl7.fhir.dstu3.model.ElementDefinition;
077import org.hl7.fhir.dstu3.model.Extension;
078import org.hl7.fhir.dstu3.model.ExtensionHelper;
079import org.hl7.fhir.dstu3.model.Factory;
080import org.hl7.fhir.dstu3.model.Identifier;
081import org.hl7.fhir.dstu3.model.IntegerType;
082import org.hl7.fhir.dstu3.model.MarkdownType;
083import org.hl7.fhir.dstu3.model.PrimitiveType;
084import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemComponent;
085import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType;
086import org.hl7.fhir.dstu3.model.StringType;
087import org.hl7.fhir.dstu3.model.Type;
088import org.hl7.fhir.dstu3.model.UriType;
089import org.hl7.fhir.dstu3.model.ValueSet.ConceptReferenceComponent;
090import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
091import org.hl7.fhir.dstu3.model.BackboneElement;
092import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage;
093import org.hl7.fhir.utilities.Utilities;
094import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
095
096
097@MarkedToMoveToAdjunctPackage
098public class ExtensionUtilities {
099
100  // validated
101  public static final String EXT_SUBSUMES = "http://hl7.org/fhir/StructureDefinition/codesystem-subsumes"; 
102//  private static final String EXT_OID = "http://hl7.org/fhir/StructureDefinition/valueset-oid";
103//  public static final String EXT_DEPRECATED = "http://hl7.org/fhir/StructureDefinition/codesystem-deprecated";
104  public static final String EXT_DEFINITION = "http://hl7.org/fhir/StructureDefinition/valueset-definition";
105  public static final String EXT_CS_COMMENT = "http://hl7.org/fhir/StructureDefinition/codesystem-comments";
106  public static final String EXT_VS_COMMENT = "http://hl7.org/fhir/StructureDefinition/valueset-comments";
107  private static final String EXT_IDENTIFIER = "http://hl7.org/fhir/StructureDefinition/identifier";
108  public static final String EXT_TRANSLATION = "http://hl7.org/fhir/StructureDefinition/translation";
109  public static final String EXT_ISSUE_SOURCE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-source";
110  public static final String EXT_DISPLAY_HINT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-display-hint"; 
111  public static final String EXT_REPLACED_BY = "http://hl7.org/fhir/StructureDefinition/valueset-replacedby";
112  public static final String EXT_JSON_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type"; 
113  public static final String EXT_RDF_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-rdf-type"; 
114  public static final String EXT_XML_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-type"; 
115  public static final String EXT_REGEX = "http://hl7.org/fhir/StructureDefinition/structuredefinition-regex"; 
116  public static final String EXT_CONTROL = "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl"; 
117  public static final String EXT_MINOCCURS = "http://hl7.org/fhir/StructureDefinition/questionnaire-minOccurs"; 
118  public static final String EXT_MAXOCCURS = "http://hl7.org/fhir/StructureDefinition/questionnaire-maxOccurs";
119  public static final String EXT_ALLOWEDRESOURCE = "http://hl7.org/fhir/StructureDefinition/questionnaire-allowedResource";
120  public static final String EXT_REFERENCEFILTER = "http://hl7.org/fhir/StructureDefinition/questionnaire-referenceFilter";
121  public static final String EXT_CODE_GENERATION_PARENT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-codegen-super";
122
123  // unregistered?
124  public static final String EXT_MAPPING_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/logical-mapping-prefix";
125  public static final String EXT_MAPPING_SUFFIX = "http://hl7.org/fhir/tools/StructureDefinition/logical-mapping-suffix";
126
127//  public static final String EXT_FLYOVER = "http://hl7.org/fhir/Profile/questionnaire-extensions#flyover";
128  public static final String EXT_QTYPE = "http://hl7.org/fhir/StructureDefinition/questionnnaire-baseType";
129//  private static final String EXT_QREF = "http://www.healthintersections.com.au/fhir/Profile/metadata#reference";
130//  private static final String EXTENSION_FILTER_ONLY = "http://www.healthintersections.com.au/fhir/Profile/metadata#expandNeedsFilter";
131//  private static final String EXT_TYPE = "http://www.healthintersections.com.au/fhir/Profile/metadata#type";
132//  private static final String EXT_REFERENCE = "http://www.healthintersections.com.au/fhir/Profile/metadata#reference";
133  private static final String EXT_FHIRTYPE = "http://hl7.org/fhir/StructureDefinition/questionnaire-fhirType";
134  private static final String EXT_ALLOWABLE_UNITS = "http://hl7.org/fhir/StructureDefinition/elementdefinition-allowedUnits";
135  public static final String EXT_CIMI_REFERENCE = "http://hl7.org/fhir/StructureDefinition/cimi-reference";
136  public static final String EXT_UNCLOSED = "http://hl7.org/fhir/StructureDefinition/valueset-unclosed";
137  public static final String EXT_FMM_LEVEL = "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm";
138  public static final String EXT_RESOURCE_CATEGORY = "http://hl7.org/fhir/StructureDefinition/structuredefinition-category";
139  public static final String EXT_TABLE_NAME = "http://hl7.org/fhir/StructureDefinition/structuredefinition-table-name";
140  public static final String EXT_OO_FILE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-file";
141  public static final String EXT_WORKGROUP = "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg";
142  public static final String EXT_BALLOT_STATUS = "http://hl7.org/fhir/StructureDefinition/structuredefinition-ballot-status";
143
144
145  // specific extension helpers
146
147  public static Extension makeIssueSource(Source source) {
148    Extension ex = new Extension();
149    // todo: write this up and get it published with the pack (and handle the redirect?)
150    ex.setUrl(ExtensionUtilities.EXT_ISSUE_SOURCE);
151    CodeType c = new CodeType();
152    c.setValue(source.toString());
153    ex.setValue(c);
154    return ex;
155  }
156
157  public static boolean hasExtension(DomainResource de, String url) {
158    return getExtension(de, url) != null;
159  }
160
161  public static boolean hasExtension(Element e, String url) {
162    return getExtension(e, url) != null;
163  }
164
165//  public static void addStringExtension(DomainResource dr, String url, String content) {
166//    if (!StringUtils.isBlank(content)) {
167//      Extension ex = getExtension(dr, url);
168//      if (ex != null)
169//        ex.setValue(new StringType(content));
170//      else
171//        dr.getExtension().add(Factory.newExtension(url, new StringType(content), true));   
172//    }
173//  }
174
175  public static void addMarkdownExtension(DomainResource dr, String url, String content) {
176    if (!StringUtils.isBlank(content)) {
177      Extension ex = getExtension(dr, url);
178      if (ex != null)
179        ex.setValue(new StringType(content));
180      else
181        dr.getExtension().add(Factory.newExtension(url, new MarkdownType(content), true));   
182    }
183  }
184
185  public static void addStringExtension(Element e, String url, String content) {
186    if (!StringUtils.isBlank(content)) {
187      Extension ex = getExtension(e, url);
188      if (ex != null)
189        ex.setValue(new StringType(content));
190      else
191        e.getExtension().add(Factory.newExtension(url, new StringType(content), true));   
192    }
193  }
194
195  public static void addStringExtension(DomainResource e, String url, String content) {
196    if (!StringUtils.isBlank(content)) {
197      Extension ex = getExtension(e, url);
198      if (ex != null)
199        ex.setValue(new StringType(content));
200      else
201        e.getExtension().add(Factory.newExtension(url, new StringType(content), true));   
202    }
203  }
204
205  public static void addIntegerExtension(DomainResource dr, String url, int value) {
206    Extension ex = getExtension(dr, url);
207    if (ex != null)
208      ex.setValue(new IntegerType(value));
209    else
210      dr.getExtension().add(Factory.newExtension(url, new IntegerType(value), true));   
211  }
212
213  public static void addVSComment(ConceptSetComponent nc, String comment) {
214    if (!StringUtils.isBlank(comment))
215      nc.getExtension().add(Factory.newExtension(EXT_VS_COMMENT, Factory.newString_(comment), true));   
216  }
217  public static void addVSComment(ConceptReferenceComponent nc, String comment) {
218    if (!StringUtils.isBlank(comment))
219      nc.getExtension().add(Factory.newExtension(EXT_VS_COMMENT, Factory.newString_(comment), true));   
220  }
221
222  public static void addCSComment(ConceptDefinitionComponent nc, String comment) {
223    if (!StringUtils.isBlank(comment))
224      nc.getExtension().add(Factory.newExtension(EXT_CS_COMMENT, Factory.newString_(comment), true));   
225  }
226
227//  public static void markDeprecated(Element nc) {
228//    setDeprecated(nc);   
229//  }
230//
231  public static void addSubsumes(ConceptDefinitionComponent nc, String code) {
232    nc.getModifierExtension().add(Factory.newExtension(EXT_SUBSUMES, Factory.newCode(code), true));   
233  }
234
235  public static void addDefinition(Element nc, String definition) {
236    if (!StringUtils.isBlank(definition))
237      nc.getExtension().add(Factory.newExtension(EXT_DEFINITION, Factory.newString_(definition), true));   
238  }
239
240  public static void addDisplayHint(Element def, String hint) {
241    if (!StringUtils.isBlank(hint))
242      def.getExtension().add(Factory.newExtension(EXT_DISPLAY_HINT, Factory.newString_(hint), true));   
243  }
244
245  public static String getDisplayHint(Element def) {
246    return readStringExtension(def, EXT_DISPLAY_HINT);    
247  }
248
249  public static String readStringExtension(Element c, String uri) {
250    Extension ex = ExtensionHelper.getExtension(c, uri);
251    if (ex == null)
252      return null;
253    if (ex.getValue() instanceof UriType)
254      return ((UriType) ex.getValue()).getValue();
255    if (ex.getValue() instanceof CodeType)
256      return ((CodeType) ex.getValue()).getValue();
257    if (ex.getValue() instanceof IntegerType)
258      return ((IntegerType) ex.getValue()).asStringValue();
259    if ((ex.getValue() instanceof MarkdownType))
260      return ((MarkdownType) ex.getValue()).getValue();
261    if (!(ex.getValue() instanceof StringType))
262      return null;
263    return ((StringType) ex.getValue()).getValue();
264  }
265
266  public static String readStringExtension(DomainResource c, String uri) {
267    Extension ex = getExtension(c, uri);
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 MarkdownType))
279      return ((MarkdownType) ex.getValue()).getValue();
280    return null;
281  }
282
283  @SuppressWarnings("unchecked")
284  public static PrimitiveType<Type> readPrimitiveExtension(DomainResource c, String uri) {
285    Extension ex = getExtension(c, uri);
286    if (ex == null)
287      return null;
288    return (PrimitiveType<Type>) ex.getValue();
289  }
290
291  public static boolean findStringExtension(Element c, String uri) {
292    Extension ex = ExtensionHelper.getExtension(c, uri);
293    if (ex == null)
294      return false;
295    if (!(ex.getValue() instanceof StringType))
296      return false;
297    return !StringUtils.isBlank(((StringType) ex.getValue()).getValue());
298  }
299
300  public static Boolean readBooleanExtension(Element c, String uri) {
301    Extension ex = ExtensionHelper.getExtension(c, uri);
302    if (ex == null)
303      return null;
304    if (!(ex.getValue() instanceof BooleanType))
305      return null;
306    return ((BooleanType) ex.getValue()).getValue();
307  }
308
309  public static boolean findBooleanExtension(Element c, String uri) {
310    Extension ex = ExtensionHelper.getExtension(c, uri);
311    if (ex == null)
312      return false;
313    if (!(ex.getValue() instanceof BooleanType))
314      return false;
315    return true;
316  }
317
318  public static String getCSComment(ConceptDefinitionComponent c) {
319    return readStringExtension(c, EXT_CS_COMMENT);    
320  }
321//
322//  public static Boolean getDeprecated(Element c) {
323//    return readBooleanExtension(c, EXT_DEPRECATED);    
324//  }
325
326  public static boolean hasCSComment(ConceptDefinitionComponent c) {
327    return findStringExtension(c, EXT_CS_COMMENT);    
328  }
329
330//  public static boolean hasDeprecated(Element c) {
331//    return findBooleanExtension(c, EXT_DEPRECATED);    
332//  }
333
334  public static List<CodeType> getSubsumes(ConceptDefinitionComponent c) {
335    List<CodeType> res = new ArrayList<CodeType>();
336
337    for (Extension e : c.getExtension()) {
338      if (EXT_SUBSUMES.equals(e.getUrl()))
339        res.add((CodeType) e.getValue());
340    }
341    return res;
342  }
343
344  public static void addFlyOver(QuestionnaireItemComponent item, String text){
345    if (!StringUtils.isBlank(text)) {
346        QuestionnaireItemComponent display = item.addItem();
347        display.setType(QuestionnaireItemType.DISPLAY);
348        display.setText(text);
349        display.getExtension().add(Factory.newExtension(EXT_CONTROL, Factory.newCodeableConcept("flyover", "http://hl7.org/fhir/questionnaire-item-control", "Fly-over"), true));
350    }
351  }
352
353  public static void addMin(QuestionnaireItemComponent item, int min) {
354    item.getExtension().add(Factory.newExtension(EXT_MINOCCURS, Factory.newInteger(min), true));
355  }
356  
357  public static void addMax(QuestionnaireItemComponent item, int max) {
358    item.getExtension().add(Factory.newExtension(EXT_MAXOCCURS, Factory.newInteger(max), true));
359  }
360  
361  public static void addFhirType(QuestionnaireItemComponent group, String value) {
362    group.getExtension().add(Factory.newExtension(EXT_FHIRTYPE, Factory.newString_(value), true));       
363  }
364
365  public static void addControl(QuestionnaireItemComponent group, String value) {
366    group.getExtension().add(Factory.newExtension(EXT_CONTROL, Factory.newCodeableConcept(value, "http://hl7.org/fhir/questionnaire-item-control", value), true));
367  }
368
369  public static void addAllowedResource(QuestionnaireItemComponent group, String value) {
370    group.getExtension().add(Factory.newExtension(EXT_ALLOWEDRESOURCE, Factory.newCode(value), true));       
371  }
372
373  public static void addReferenceFilter(QuestionnaireItemComponent group, String value) {
374    group.getExtension().add(Factory.newExtension(EXT_REFERENCEFILTER, Factory.newString_(value), true));       
375  }
376
377  public static void addIdentifier(Element element, Identifier value) {
378    element.getExtension().add(Factory.newExtension(EXT_IDENTIFIER, value, true));       
379  }
380
381  /**
382   * @param name the identity of the extension of interest
383   * @return The extension, if on this element, else null
384   */
385  public static Extension getExtension(DomainResource resource, String name) {
386    if (name == null)
387      return null;
388    if (!resource.hasExtension())
389      return null;
390    for (Extension e : resource.getExtension()) {
391      if (name.equals(e.getUrl()))
392        return e;
393    }
394    return null;
395  }
396
397  public static Extension getExtension(Element el, String name) {
398    if (name == null)
399      return null;
400    if (!el.hasExtension())
401      return null;
402    for (Extension e : el.getExtension()) {
403      if (name.equals(e.getUrl()))
404        return e;
405    }
406    return null;
407  }
408
409  public static void setStringExtension(DomainResource resource, String uri, String value) {
410    Extension ext = getExtension(resource, uri);
411    if (ext != null)
412      ext.setValue(new StringType(value));
413    else
414      resource.getExtension().add(new Extension(new UriType(uri)).setValue(new StringType(value)));
415  }
416
417  public static void setStringExtension(Element element, String uri, String value) {
418    Extension ext = getExtension(element, uri);
419    if (ext != null)
420      ext.setValue(new StringType(value));
421    else
422      element.getExtension().add(new Extension(new UriType(uri)).setValue(new StringType(value)));
423  }
424
425  public static void setCodeExtension(DomainResource resource, String uri, String value) {
426    Extension ext = getExtension(resource, uri);
427    if (ext != null)
428      ext.setValue(new CodeType(value));
429    else
430      resource.getExtension().add(new Extension(new UriType(uri)).setValue(new CodeType(value)));
431  }
432
433  public static void setIntegerExtension(DomainResource resource, String uri, int value) {
434    Extension ext = getExtension(resource, uri);
435    if (ext != null)
436      ext.setValue(new IntegerType(value));
437    else
438      resource.getExtension().add(new Extension(new UriType(uri)).setValue(new IntegerType(value)));
439  }
440  
441
442  public static void setCodeExtensionMod(DomainResource resource, String uri, String value) {
443    if (Utilities.noString(value))
444      return;
445
446    Extension ext = getExtension(resource, uri);
447    if (ext != null)
448      ext.setValue(new CodeType(value));
449    else
450      resource.getModifierExtension().add(new Extension(uri).setValue(new CodeType(value)));
451  }
452
453  public static void setCodeExtensionMod(BackboneElement resource, String uri, String value) {
454    if (Utilities.noString(value))
455      return;
456
457    Extension ext = getExtension(resource, uri);
458    if (ext != null)
459      ext.setValue(new CodeType(value));
460    else
461      resource.getModifierExtension().add(new Extension(uri).setValue(new CodeType(value)));
462  }
463
464//  public static String getOID(CodeSystem define) {
465//    return readStringExtension(define, EXT_OID);    
466//  }
467//
468//  public static String getOID(ValueSet vs) {
469//    return readStringExtension(vs, EXT_OID);    
470//  }
471//
472//  public static void setOID(CodeSystem define, String oid) throws FHIRFormatError, URISyntaxException {
473//    if (!oid.startsWith("urn:oid:"))
474//      throw new FHIRFormatError("Error in OID format");
475//    if (oid.startsWith("urn:oid:urn:oid:"))
476//      throw new FHIRFormatError("Error in OID format");
477//    if (!hasExtension(define, EXT_OID))
478//    define.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false));       
479//    else if (!oid.equals(readStringExtension(define, EXT_OID)))
480//      throw new Error("Attempt to assign multiple OIDs to a code system");
481//  }
482//  public static void setOID(ValueSet vs, String oid) throws FHIRFormatError, URISyntaxException {
483//    if (!oid.startsWith("urn:oid:"))
484//      throw new FHIRFormatError("Error in OID format");
485//    if (oid.startsWith("urn:oid:urn:oid:"))
486//      throw new FHIRFormatError("Error in OID format");
487//    if (!hasExtension(vs, EXT_OID))
488//    vs.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false));       
489//    else if (!oid.equals(readStringExtension(vs, EXT_OID)))
490//      throw new Error("Attempt to assign multiple OIDs to value set "+vs.getName()+" ("+vs.getUrl()+"). Has "+readStringExtension(vs, EXT_OID)+", trying to add "+oid);
491//  }
492
493  public static boolean hasLanguageTranslation(Element element, String lang) {
494    for (Extension e : element.getExtension()) {
495      if (e.getUrl().equals(EXT_TRANSLATION)) {
496        Extension e1 = ExtensionHelper.getExtension(e, "lang");
497
498        if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang))
499          return true;
500      }
501    }
502    return false;
503  }
504
505  public static String getLanguageTranslation(Element element, String lang) {
506    for (Extension e : element.getExtension()) {
507      if (e.getUrl().equals(EXT_TRANSLATION)) {
508        Extension e1 = ExtensionHelper.getExtension(e, "lang");
509
510        if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang)) {
511          e1 = ExtensionHelper.getExtension(e, "content");
512          return ((StringType) e.getValue()).getValue();
513        }
514      }
515    }
516    return null;
517  }
518
519  public static void addLanguageTranslation(Element element, String lang, String value) {
520    Extension extension = new Extension().setUrl(EXT_TRANSLATION);
521    extension.addExtension().setUrl("lang").setValue(new StringType(lang));
522    extension.addExtension().setUrl("content").setValue(new StringType(value));
523    element.getExtension().add(extension);
524  }
525
526  public static Type getAllowedUnits(ElementDefinition eld) {
527    for (Extension e : eld.getExtension()) 
528      if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) 
529        return e.getValue();
530    return null;
531  }
532
533  public static void setAllowableUnits(ElementDefinition eld, CodeableConcept cc) {
534    for (Extension e : eld.getExtension()) 
535      if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) {
536        e.setValue(cc);
537        return;
538      }
539    eld.getExtension().add(new Extension().setUrl(EXT_ALLOWABLE_UNITS).setValue(cc));
540  }
541
542  public static List<Extension> getExtensions(Element element, String url) {
543    List<Extension> results = new ArrayList<Extension>();
544    for (Extension ex : element.getExtension())
545      if (ex.getUrl().equals(url))
546        results.add(ex);
547    return results;
548  }
549
550  public static List<Extension> getExtensions(DomainResource resource, String url) {
551    List<Extension> results = new ArrayList<Extension>();
552    for (Extension ex : resource.getExtension())
553      if (ex.getUrl().equals(url))
554        results.add(ex);
555    return results;
556  }
557
558  public static void addDEReference(DataElement de, String value) {
559    for (Extension e : de.getExtension()) 
560      if (e.getUrl().equals(EXT_CIMI_REFERENCE)) {
561        e.setValue(new UriType(value));
562        return;
563      }
564    de.getExtension().add(new Extension().setUrl(EXT_CIMI_REFERENCE).setValue(new UriType(value)));
565  }
566
567//  public static void setDeprecated(Element nc) {
568//    for (Extension e : nc.getExtension()) 
569//      if (e.getUrl().equals(EXT_DEPRECATED)) {
570//        e.setValue(new BooleanType(true));
571//        return;
572//      }
573//    nc.getExtension().add(new Extension().setUrl(EXT_DEPRECATED).setValue(new BooleanType(true)));    
574//  }
575
576  public static void setExtension(Element focus, String url, Coding c) {
577    for (Extension e : focus.getExtension()) 
578      if (e.getUrl().equals(url)) {
579        e.setValue(c);
580        return;
581      }
582    focus.getExtension().add(new Extension().setUrl(url).setValue(c));    
583  }
584
585  public static void removeExtension(DomainResource focus, String url) {
586    Iterator<Extension> i = focus.getExtension().iterator();
587    while (i.hasNext()) {
588      Extension e = i.next(); // must be called before you can call i.remove()
589      if (e.getUrl().equals(url)) {
590        i.remove();
591      }
592    }
593  }
594  
595  public static void removeExtension(Element focus, String url) {
596    Iterator<Extension> i = focus.getExtension().iterator();
597    while (i.hasNext()) {
598      Extension e = i.next(); // must be called before you can call i.remove()
599      if (e.getUrl().equals(url)) {
600        i.remove();
601      }
602    }
603  }
604
605  public static int readIntegerExtension(DomainResource dr, String uri, int defaultValue) {
606    Extension ex = ExtensionHelper.getExtension(dr, uri);
607    if (ex == null)
608      return defaultValue;
609    if (ex.getValue() instanceof IntegerType)
610      return ((IntegerType) ex.getValue()).getValue();
611    throw new Error("Unable to read extension "+uri+" as an integer");
612  }
613
614//  public static boolean hasOID(ValueSet vs) {
615//    return hasExtension(vs, EXT_OID);
616//  }
617//  
618//  public static boolean hasOID(CodeSystem cs) {
619//    return hasExtension(cs, EXT_OID);
620//  }
621//  
622  
623}