001package ca.uhn.fhir.util; 002 003import static org.apache.commons.lang3.StringUtils.isNotBlank; 004 005/* 006 * #%L 007 * HAPI FHIR - Core Library 008 * %% 009 * Copyright (C) 2014 - 2017 University Health Network 010 * %% 011 * Licensed under the Apache License, Version 2.0 (the "License"); 012 * you may not use this file except in compliance with the License. 013 * You may obtain a copy of the License at 014 * 015 * http://www.apache.org/licenses/LICENSE-2.0 016 * 017 * Unless required by applicable law or agreed to in writing, software 018 * distributed under the License is distributed on an "AS IS" BASIS, 019 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 020 * See the License for the specific language governing permissions and 021 * limitations under the License. 022 * #L% 023 */ 024 025import java.util.ArrayList; 026import java.util.List; 027 028import org.apache.commons.lang3.tuple.Pair; 029import org.hl7.fhir.instance.model.api.*; 030 031import ca.uhn.fhir.context.*; 032import ca.uhn.fhir.rest.api.RequestTypeEnum; 033 034/** 035 * Fetch resources from a bundle 036 */ 037public class BundleUtil { 038 039 @SuppressWarnings("unchecked") 040 public static List<Pair<String, IBaseResource>> getBundleEntryUrlsAndResources(FhirContext theContext, IBaseBundle theBundle) { 041 RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle); 042 BaseRuntimeChildDefinition entryChild = def.getChildByName("entry"); 043 List<IBase> entries = entryChild.getAccessor().getValues(theBundle); 044 045 BaseRuntimeElementCompositeDefinition<?> entryChildElem = (BaseRuntimeElementCompositeDefinition<?>) entryChild.getChildByName("entry"); 046 BaseRuntimeChildDefinition resourceChild = entryChildElem.getChildByName("resource"); 047 048 BaseRuntimeChildDefinition requestChild = entryChildElem.getChildByName("request"); 049 BaseRuntimeElementCompositeDefinition<?> requestDef = (BaseRuntimeElementCompositeDefinition<?>) requestChild.getChildByName("request"); 050 051 BaseRuntimeChildDefinition urlChild = requestDef.getChildByName("url"); 052 053 List<Pair<String, IBaseResource>> retVal = new ArrayList<Pair<String,IBaseResource>>(entries.size()); 054 for (IBase nextEntry : entries) { 055 056 String url = null; 057 IBaseResource resource = null; 058 059 for (IBase nextEntryValue : requestChild.getAccessor().getValues(nextEntry)) { 060 for (IBase nextUrlValue : urlChild.getAccessor().getValues(nextEntryValue)) { 061 url = ((IPrimitiveType<String>)nextUrlValue).getValue(); 062 } 063 } 064 065 // Should return 0..1 only 066 for (IBase nextValue : resourceChild.getAccessor().getValues(nextEntry)) { 067 resource = (IBaseResource) nextValue; 068 } 069 070 retVal.add(Pair.of(url, resource)); 071 } 072 073 return retVal; 074 } 075 076 public static String getBundleType(FhirContext theContext, IBaseBundle theBundle) { 077 RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle); 078 BaseRuntimeChildDefinition entryChild = def.getChildByName("type"); 079 List<IBase> entries = entryChild.getAccessor().getValues(theBundle); 080 if (entries.size() > 0) { 081 IPrimitiveType<?> typeElement = (IPrimitiveType<?>) entries.get(0); 082 return typeElement.getValueAsString(); 083 } 084 return null; 085 } 086 087 /** 088 * Extract all of the resources from a given bundle 089 */ 090 public static List<BundleEntryParts> toListOfEntries(FhirContext theContext, IBaseBundle theBundle) { 091 List<BundleEntryParts> retVal = new ArrayList<BundleEntryParts>(); 092 093 RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle); 094 BaseRuntimeChildDefinition entryChild = def.getChildByName("entry"); 095 List<IBase> entries = entryChild.getAccessor().getValues(theBundle); 096 097 BaseRuntimeElementCompositeDefinition<?> entryChildElem = (BaseRuntimeElementCompositeDefinition<?>) entryChild.getChildByName("entry"); 098 099 BaseRuntimeChildDefinition resourceChild = entryChildElem.getChildByName("resource"); 100 BaseRuntimeChildDefinition requestChild = entryChildElem.getChildByName("request"); 101 BaseRuntimeElementCompositeDefinition<?> requestElem = (BaseRuntimeElementCompositeDefinition<?>) requestChild.getChildByName("request"); 102 BaseRuntimeChildDefinition urlChild = requestElem.getChildByName("url"); 103 BaseRuntimeChildDefinition methodChild = requestElem.getChildByName("method"); 104 105 IBaseResource resource = null; 106 String url = null; 107 RequestTypeEnum requestType = null; 108 109 for (IBase nextEntry : entries) { 110 for (IBase next : resourceChild.getAccessor().getValues(nextEntry)) { 111 resource = (IBaseResource) next; 112 } 113 for (IBase nextRequest : requestChild.getAccessor().getValues(nextEntry)) { 114 for (IBase nextUrl : urlChild.getAccessor().getValues(nextRequest)) { 115 url = ((IPrimitiveType<?>)nextUrl).getValueAsString(); 116 } 117 for (IBase nextUrl : methodChild.getAccessor().getValues(nextRequest)) { 118 String methodString = ((IPrimitiveType<?>)nextUrl).getValueAsString(); 119 if (isNotBlank(methodString)) { 120 requestType = RequestTypeEnum.valueOf(methodString); 121 } 122 } 123 } 124 125 /* 126 * All 3 might be null - That's ok because we still want to know the 127 * order in the original bundle. 128 */ 129 retVal.add(new BundleEntryParts(requestType, url, resource)); 130 } 131 132 133 return retVal; 134 } 135 136 /** 137 * Extract all of the resources from a given bundle 138 */ 139 public static List<IBaseResource> toListOfResources(FhirContext theContext, IBaseBundle theBundle) { 140 return toListOfResourcesOfType(theContext, theBundle, null); 141 } 142 143 /** 144 * Extract all of the resources of a given type from a given bundle 145 */ 146 @SuppressWarnings("unchecked") 147 public static <T extends IBaseResource> List<T> toListOfResourcesOfType(FhirContext theContext, IBaseBundle theBundle, Class<T> theTypeToInclude) { 148 List<T> retVal = new ArrayList<T>(); 149 150 RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle); 151 BaseRuntimeChildDefinition entryChild = def.getChildByName("entry"); 152 List<IBase> entries = entryChild.getAccessor().getValues(theBundle); 153 154 BaseRuntimeElementCompositeDefinition<?> entryChildElem = (BaseRuntimeElementCompositeDefinition<?>) entryChild.getChildByName("entry"); 155 BaseRuntimeChildDefinition resourceChild = entryChildElem.getChildByName("resource"); 156 for (IBase nextEntry : entries) { 157 for (IBase next : resourceChild.getAccessor().getValues(nextEntry)) { 158 if (theTypeToInclude != null && !theTypeToInclude.isAssignableFrom(next.getClass())) { 159 continue; 160 } 161 retVal.add((T) next); 162 } 163 } 164 165 return retVal; 166 } 167 168 public static class BundleEntryParts 169 { 170 private final RequestTypeEnum myRequestType; 171 private final IBaseResource myResource; 172 private final String myUrl; 173 public BundleEntryParts(RequestTypeEnum theRequestType, String theUrl, IBaseResource theResource) { 174 super(); 175 myRequestType = theRequestType; 176 myUrl = theUrl; 177 myResource = theResource; 178 } 179 public RequestTypeEnum getRequestType() { 180 return myRequestType; 181 } 182 public IBaseResource getResource() { 183 return myResource; 184 } 185 public String getUrl() { 186 return myUrl; 187 } 188 } 189 190}