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.IBase; 030import org.hl7.fhir.instance.model.api.IBaseBundle; 031import org.hl7.fhir.instance.model.api.IBaseResource; 032import org.hl7.fhir.instance.model.api.IPrimitiveType; 033 034import ca.uhn.fhir.context.BaseRuntimeChildDefinition; 035import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; 036import ca.uhn.fhir.context.FhirContext; 037import ca.uhn.fhir.context.RuntimeResourceDefinition; 038import ca.uhn.fhir.rest.api.RequestTypeEnum; 039 040/** 041 * Fetch resources from a bundle 042 */ 043public class BundleUtil { 044 045 @SuppressWarnings("unchecked") 046 public static List<Pair<String, IBaseResource>> getBundleEntryUrlsAndResources(FhirContext theContext, IBaseBundle theBundle) { 047 RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle); 048 BaseRuntimeChildDefinition entryChild = def.getChildByName("entry"); 049 List<IBase> entries = entryChild.getAccessor().getValues(theBundle); 050 051 BaseRuntimeElementCompositeDefinition<?> entryChildElem = (BaseRuntimeElementCompositeDefinition<?>) entryChild.getChildByName("entry"); 052 BaseRuntimeChildDefinition resourceChild = entryChildElem.getChildByName("resource"); 053 054 BaseRuntimeChildDefinition requestChild = entryChildElem.getChildByName("request"); 055 BaseRuntimeElementCompositeDefinition<?> requestDef = (BaseRuntimeElementCompositeDefinition<?>) requestChild.getChildByName("request"); 056 057 BaseRuntimeChildDefinition urlChild = requestDef.getChildByName("url"); 058 059 List<Pair<String, IBaseResource>> retVal = new ArrayList<Pair<String,IBaseResource>>(entries.size()); 060 for (IBase nextEntry : entries) { 061 062 String url = null; 063 IBaseResource resource = null; 064 065 for (IBase nextEntryValue : requestChild.getAccessor().getValues(nextEntry)) { 066 for (IBase nextUrlValue : urlChild.getAccessor().getValues(nextEntryValue)) { 067 url = ((IPrimitiveType<String>)nextUrlValue).getValue(); 068 } 069 } 070 071 // Should return 0..1 only 072 for (IBase nextValue : resourceChild.getAccessor().getValues(nextEntry)) { 073 resource = (IBaseResource) nextValue; 074 } 075 076 retVal.add(Pair.of(url, resource)); 077 } 078 079 return retVal; 080 } 081 082 public static String getBundleType(FhirContext theContext, IBaseBundle theBundle) { 083 RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle); 084 BaseRuntimeChildDefinition entryChild = def.getChildByName("type"); 085 List<IBase> entries = entryChild.getAccessor().getValues(theBundle); 086 if (entries.size() > 0) { 087 IPrimitiveType<?> typeElement = (IPrimitiveType<?>) entries.get(0); 088 return typeElement.getValueAsString(); 089 } 090 return null; 091 } 092 093 /** 094 * Extract all of the resources from a given bundle 095 */ 096 public static List<BundleEntryParts> toListOfEntries(FhirContext theContext, IBaseBundle theBundle) { 097 List<BundleEntryParts> retVal = new ArrayList<BundleEntryParts>(); 098 099 RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle); 100 BaseRuntimeChildDefinition entryChild = def.getChildByName("entry"); 101 List<IBase> entries = entryChild.getAccessor().getValues(theBundle); 102 103 BaseRuntimeElementCompositeDefinition<?> entryChildElem = (BaseRuntimeElementCompositeDefinition<?>) entryChild.getChildByName("entry"); 104 105 BaseRuntimeChildDefinition resourceChild = entryChildElem.getChildByName("resource"); 106 BaseRuntimeChildDefinition requestChild = entryChildElem.getChildByName("request"); 107 BaseRuntimeElementCompositeDefinition<?> requestElem = (BaseRuntimeElementCompositeDefinition<?>) requestChild.getChildByName("request"); 108 BaseRuntimeChildDefinition urlChild = requestElem.getChildByName("url"); 109 BaseRuntimeChildDefinition methodChild = requestElem.getChildByName("method"); 110 111 IBaseResource resource = null; 112 String url = null; 113 RequestTypeEnum requestType = null; 114 115 for (IBase nextEntry : entries) { 116 for (IBase next : resourceChild.getAccessor().getValues(nextEntry)) { 117 resource = (IBaseResource) next; 118 } 119 for (IBase nextRequest : requestChild.getAccessor().getValues(nextEntry)) { 120 for (IBase nextUrl : urlChild.getAccessor().getValues(nextRequest)) { 121 url = ((IPrimitiveType<?>)nextUrl).getValueAsString(); 122 } 123 for (IBase nextUrl : methodChild.getAccessor().getValues(nextRequest)) { 124 String methodString = ((IPrimitiveType<?>)nextUrl).getValueAsString(); 125 if (isNotBlank(methodString)) { 126 requestType = RequestTypeEnum.valueOf(methodString); 127 } 128 } 129 } 130 131 /* 132 * All 3 might be null - That's ok because we still want to know the 133 * order in the original bundle. 134 */ 135 retVal.add(new BundleEntryParts(requestType, url, resource)); 136 } 137 138 139 return retVal; 140 } 141 142 /** 143 * Extract all of the resources from a given bundle 144 */ 145 public static List<IBaseResource> toListOfResources(FhirContext theContext, IBaseBundle theBundle) { 146 List<IBaseResource> retVal = new ArrayList<IBaseResource>(); 147 148 RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle); 149 BaseRuntimeChildDefinition entryChild = def.getChildByName("entry"); 150 List<IBase> entries = entryChild.getAccessor().getValues(theBundle); 151 152 BaseRuntimeElementCompositeDefinition<?> entryChildElem = (BaseRuntimeElementCompositeDefinition<?>) entryChild.getChildByName("entry"); 153 BaseRuntimeChildDefinition resourceChild = entryChildElem.getChildByName("resource"); 154 for (IBase nextEntry : entries) { 155 for (IBase next : resourceChild.getAccessor().getValues(nextEntry)) { 156 retVal.add((IBaseResource) next); 157 } 158 } 159 160 return retVal; 161 } 162 163 public static class BundleEntryParts 164 { 165 private final RequestTypeEnum myRequestType; 166 private final IBaseResource myResource; 167 private final String myUrl; 168 public BundleEntryParts(RequestTypeEnum theRequestType, String theUrl, IBaseResource theResource) { 169 super(); 170 myRequestType = theRequestType; 171 myUrl = theUrl; 172 myResource = theResource; 173 } 174 public RequestTypeEnum getRequestType() { 175 return myRequestType; 176 } 177 public IBaseResource getResource() { 178 return myResource; 179 } 180 public String getUrl() { 181 return myUrl; 182 } 183 } 184 185}