
001package org.hl7.fhir.r5.utils; 002 003import java.util.Collections; 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.Set; 038 039import org.hl7.fhir.r5.model.Coding; 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.Meta; 047import org.hl7.fhir.r5.model.OperationOutcome; 048import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity; 049import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent; 050import org.hl7.fhir.r5.model.Property; 051import org.hl7.fhir.r5.model.Resource; 052import org.hl7.fhir.r5.model.ResourceType; 053import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; 054import org.hl7.fhir.utilities.Utilities; 055import org.hl7.fhir.utilities.xhtml.XhtmlComposer; 056 057/** 058 * Decoration utilities for various resource types 059 * @author Grahame 060 * 061 */ 062public class ResourceUtilities { 063 064 public final static String FHIR_LANGUAGE = "urn:ietf:bcp:47"; 065 private static JurisdictionLocales jl = new JurisdictionLocales(); 066 067 public static boolean isAnError(OperationOutcome error) { 068 for (OperationOutcomeIssueComponent t : error.getIssue()) 069 if (t.getSeverity() == IssueSeverity.ERROR) 070 return true; 071 else if (t.getSeverity() == IssueSeverity.FATAL) 072 return true; 073 return false; 074 } 075 076 public static String getErrorDescription(OperationOutcome error) { 077 if (error.hasText() && error.getText().hasDiv()) { 078 return new XhtmlComposer(XhtmlComposer.XML).composePlainText(error.getText().getDiv()); 079 } 080 081 StringBuilder b = new StringBuilder(); 082 for (OperationOutcomeIssueComponent t : error.getIssue()) { 083 if (t.getSeverity() == IssueSeverity.ERROR) { 084 b.append("Error: " +gen(t.getDetails())+"\r\n"); 085 } else if (t.getSeverity() == IssueSeverity.FATAL) { 086 b.append("Fatal: " +gen(t.getDetails())+"\r\n"); 087 } else if (t.getSeverity() == IssueSeverity.WARNING) { 088 b.append("Warning: " +gen(t.getDetails())+"\r\n"); 089 } else if (t.getSeverity() == IssueSeverity.INFORMATION) { 090 b.append("Information: " +gen(t.getDetails())+"\r\n"); 091 } 092 } 093 return b.toString(); 094 } 095 096 097 private static String gen(CodeableConcept details) { 098 if (details.hasText()) { 099 return details.getText(); 100 } 101 for (Coding c : details.getCoding()) { 102 if (c.hasDisplay()) { 103 return c.getDisplay(); 104 } 105 } 106 for (Coding c : details.getCoding()) { 107 if (c.hasCode()) { 108 return c.getCode(); 109 } 110 } 111 return "(no details supplied)"; 112 } 113 114 public static Resource getById(Bundle feed, ResourceType type, String reference) { 115 for (BundleEntryComponent item : feed.getEntry()) { 116 if (item.getResource().getId().equals(reference) && item.getResource().getResourceType() == type) 117 return item.getResource(); 118 } 119 return null; 120 } 121 122 public static BundleEntryComponent getEntryById(Bundle feed, ResourceType type, String reference) { 123 for (BundleEntryComponent item : feed.getEntry()) { 124 if (item.getResource().getId().equals(reference) && item.getResource().getResourceType() == type) 125 return item; 126 } 127 return null; 128 } 129 130 public static String getLink(Bundle feed, String rel) { 131 for (BundleLinkComponent link : feed.getLink()) { 132 if (link.getRelation().toCode().equals(rel)) 133 return link.getUrl(); 134 } 135 return null; 136 } 137 138 public static Meta meta(Resource resource) { 139 if (!resource.hasMeta()) 140 resource.setMeta(new Meta()); 141 return resource.getMeta(); 142 } 143 144 public static Locale getLocale(CanonicalResource cr) { 145 return getLocale(cr.getLanguage(), cr.getJurisdiction()); 146 } 147 148 public static Locale getLocale(String lang, List<CodeableConcept> jurisdictions) { 149 if (lang != null && lang.contains("-")) { 150 return Locale.forLanguageTag(lang); 151 } 152 for (CodeableConcept cc : jurisdictions) { 153 Locale locale = getLocale(lang, cc); 154 if (locale != null) { 155 return locale; 156 } 157 } 158 return null; 159 } 160 161 162 private static Locale getLocale(String lang, CodeableConcept cc) { 163 if (cc.hasCoding("http://unstats.un.org/unsd/methods/m49/m49.htm", "001")) { 164 return new Locale("en", "US"); 165 } 166 String c = cc.getCode("urn:iso:std:iso:3166"); 167 if (c == null) { 168 return null; 169 } 170 String l = jl.get(c); 171 if (l == null) { 172 return null; 173 } else if (lang != null) { 174 return Locale.forLanguageTag(lang+"-"+l.substring(l.indexOf("-")+1)); 175 } else { 176 return Locale.forLanguageTag(l); 177 } 178 } 179 180 public static String listUrls(List<? extends CanonicalResource> list) { 181 CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); 182 for (CanonicalResource t : list) { 183 b.append(t.getVUrl()); 184 } 185 return b.toString(); 186 } 187 188 public static String listStrings(Set<String> set, boolean sort) { 189 List<String> list = Utilities.sorted(set); 190 CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); 191 for (String s : list) { 192 b.append(s); 193 } 194 if (sort) { 195 Collections.sort(list); 196 } 197 return b.toString(); 198 } 199 200 public static boolean hasURL(String uri, Resource src) { 201 for (Property p : src.children()) { 202 if (hasURL(uri, p)) { 203 return true; 204 } 205 } 206 return false; 207 } 208 209 private static boolean hasURL(String uri, Property p) { 210 for (Base b : p.getValues()) { 211 if (b.isPrimitive()) { 212 return uri.equals(b.primitiveValue()); 213 } else { 214 for (Property c : b.children()) { 215 if (hasURL(uri, c)) { 216 return true; 217 } 218 } 219 } 220 } 221 return false; 222 } 223}