001package org.hl7.fhir.r5.utils;
002
003import java.util.ArrayList;
004
005/*
006  Copyright (c) 2011+, HL7, Inc.
007  All rights reserved.
008  
009  Redistribution and use in source and binary forms, with or without modification, 
010  are permitted provided that the following conditions are met:
011    
012   * Redistributions of source code must retain the above copyright notice, this 
013     list of conditions and the following disclaimer.
014   * Redistributions in binary form must reproduce the above copyright notice, 
015     this list of conditions and the following disclaimer in the documentation 
016     and/or other materials provided with the distribution.
017   * Neither the name of HL7 nor the names of its contributors may be used to 
018     endorse or promote products derived from this software without specific 
019     prior written permission.
020  
021  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
022  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
023  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
024  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
025  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
026  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
027  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
028  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
029  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
030  POSSIBILITY OF SUCH DAMAGE.
031  
032 */
033
034
035import java.util.List;
036import java.util.Locale;
037import java.util.Map;
038import java.util.Set;
039
040import org.hl7.fhir.r5.model.Base;
041import org.hl7.fhir.r5.model.Bundle;
042import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
043import org.hl7.fhir.r5.model.Bundle.BundleLinkComponent;
044import org.hl7.fhir.r5.model.CanonicalResource;
045import org.hl7.fhir.r5.model.CodeableConcept;
046import org.hl7.fhir.r5.model.Coding;
047import org.hl7.fhir.r5.model.ContactPoint;
048import org.hl7.fhir.r5.model.ContactPoint.ContactPointSystem;
049import org.hl7.fhir.r5.model.DataType;
050import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
051import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
052import org.hl7.fhir.r5.model.Meta;
053import org.hl7.fhir.r5.model.OperationOutcome;
054import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity;
055import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
056import org.hl7.fhir.r5.model.Property;
057import org.hl7.fhir.r5.model.Reference;
058import org.hl7.fhir.r5.model.Resource;
059import org.hl7.fhir.r5.model.ResourceType;
060import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
061import org.hl7.fhir.utilities.Utilities;
062import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
063
064/**
065 * Decoration utilities for various resource types
066 * @author Grahame
067 *
068 */
069public class ResourceUtilities {
070
071  public final static String FHIR_LANGUAGE = "urn:ietf:bcp:47";
072  private static JurisdictionLocales jl = new JurisdictionLocales(); 
073
074        public static boolean isAnError(OperationOutcome error) {
075                for (OperationOutcomeIssueComponent t : error.getIssue())
076                        if (t.getSeverity() == IssueSeverity.ERROR)
077                                return true;
078                        else if (t.getSeverity() == IssueSeverity.FATAL)
079                                return true;
080                return false;
081        }
082        
083        public static String getErrorDescription(OperationOutcome error) {  
084                if (error.hasText() && error.getText().hasDiv()) {
085                        return new XhtmlComposer(XhtmlComposer.XML).composePlainText(error.getText().getDiv());
086                }
087                
088                StringBuilder b = new StringBuilder();
089                for (OperationOutcomeIssueComponent t : error.getIssue()) {
090                        if (t.getSeverity() == IssueSeverity.ERROR) {
091                                b.append("Error:" +t.getDetails()+"\r\n");
092                        } else if (t.getSeverity() == IssueSeverity.FATAL) {
093                                b.append("Fatal:" +t.getDetails()+"\r\n");
094                        } else if (t.getSeverity() == IssueSeverity.WARNING) {
095                                b.append("Warning:" +t.getDetails()+"\r\n");
096                        } else if (t.getSeverity() == IssueSeverity.INFORMATION) {
097                                b.append("Information:" +t.getDetails()+"\r\n");
098                        }
099                }
100                return b.toString();
101  }
102
103  public static Resource getById(Bundle feed, ResourceType type, String reference) {
104    for (BundleEntryComponent item : feed.getEntry()) {
105      if (item.getResource().getId().equals(reference) && item.getResource().getResourceType() == type)
106        return item.getResource();
107    }
108    return null;
109  }
110
111  public static BundleEntryComponent getEntryById(Bundle feed, ResourceType type, String reference) {
112    for (BundleEntryComponent item : feed.getEntry()) {
113      if (item.getResource().getId().equals(reference) && item.getResource().getResourceType() == type)
114        return item;
115    }
116    return null;
117  }
118
119        public static String getLink(Bundle feed, String rel) {
120                for (BundleLinkComponent link : feed.getLink()) {
121                        if (link.getRelation().equals(rel))
122                                return link.getUrl();
123                }
124          return null;
125  }
126
127  public static Meta meta(Resource resource) {
128    if (!resource.hasMeta())
129      resource.setMeta(new Meta());
130    return resource.getMeta();
131  }
132  
133  public static Locale getLocale(CanonicalResource cr) {
134    return getLocale(cr.getLanguage(), cr.getJurisdiction());
135  }
136  
137  public static Locale getLocale(String lang, List<CodeableConcept> jurisdictions) {  
138    if (lang != null && lang.contains("-")) {
139      return new Locale(lang);        
140    }
141    for (CodeableConcept cc : jurisdictions) {
142      Locale locale = getLocale(lang, cc);
143      if (locale != null) {
144        return locale;
145      }
146    }
147    return null;
148  }
149
150
151  private static Locale getLocale(String lang, CodeableConcept cc) {
152    if (cc.hasCoding("http://unstats.un.org/unsd/methods/m49/m49.htm", "001")) {
153      return new Locale("en-US");
154    }
155    String c = cc.getCode("urn:iso:std:iso:3166");
156    if (c == null) {
157      return null;
158    }
159    String l = jl.get(c);
160    if (l == null) {
161      return null;
162    } else if (lang != null) {
163      return new Locale(lang+"-"+l.substring(l.indexOf("-")+1));
164    } else {
165      return new Locale(l);
166    }
167 }
168
169  public static String listUrls(List<? extends CanonicalResource> list) {
170    CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
171    for (CanonicalResource t : list) {
172      b.append(t.getVUrl());
173    }
174    return b.toString();
175  }
176
177  public static String listStrings(Set<String> set) {
178    List<String> list = Utilities.sorted(set);
179    CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
180    for (String s : list) {
181      b.append(s);
182    }
183    return b.toString();
184  }
185
186  public static boolean hasURL(String uri, Resource src) {
187    for (Property p : src.children()) {
188      if (hasURL(uri, p)) {
189        return true;
190      }
191    }
192    return false;
193  }
194
195  private static boolean hasURL(String uri, Property p) {
196    for (Base b : p.getValues()) {
197      if (b.isPrimitive()) {
198        return uri.equals(b.primitiveValue());
199      } else {
200        for (Property c : b.children()) {
201          if (hasURL(uri, c)) {
202            return true;
203          }
204        }
205      }
206    }
207    return false;
208  }
209}