package ca.uhn.fhir.util;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
/**
* Fetch resources from a bundle
*/
public class BundleUtil {
@SuppressWarnings("unchecked")
public static List<Pair<String, IBaseResource>> getBundleEntryUrlsAndResources(FhirContext theContext, IBaseBundle theBundle) {
RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle);
BaseRuntimeChildDefinition entryChild = def.getChildByName("entry");
List<IBase> entries = entryChild.getAccessor().getValues(theBundle);
BaseRuntimeElementCompositeDefinition<?> entryChildElem = (BaseRuntimeElementCompositeDefinition<?>) entryChild.getChildByName("entry");
BaseRuntimeChildDefinition resourceChild = entryChildElem.getChildByName("resource");
BaseRuntimeChildDefinition requestChild = entryChildElem.getChildByName("request");
BaseRuntimeElementCompositeDefinition<?> requestDef = (BaseRuntimeElementCompositeDefinition<?>) requestChild.getChildByName("request");
BaseRuntimeChildDefinition urlChild = requestDef.getChildByName("url");
List<Pair<String, IBaseResource>> retVal = new ArrayList<Pair<String,IBaseResource>>(entries.size());
for (IBase nextEntry : entries) {
String url = null;
IBaseResource resource = null;
for (IBase nextEntryValue : requestChild.getAccessor().getValues(nextEntry)) {
for (IBase nextUrlValue : urlChild.getAccessor().getValues(nextEntryValue)) {
url = ((IPrimitiveType<String>)nextUrlValue).getValue();
}
}
// Should return 0..1 only
for (IBase nextValue : resourceChild.getAccessor().getValues(nextEntry)) {
resource = (IBaseResource) nextValue;
}
retVal.add(Pair.of(url, resource));
}
return retVal;
}
public static String getBundleType(FhirContext theContext, IBaseBundle theBundle) {
RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle);
BaseRuntimeChildDefinition entryChild = def.getChildByName("type");
List<IBase> entries = entryChild.getAccessor().getValues(theBundle);
if (entries.size() > 0) {
IPrimitiveType<?> typeElement = (IPrimitiveType<?>) entries.get(0);
return typeElement.getValueAsString();
}
return null;
}
/**
* Extract all of the resources from a given bundle
*/
public static List<BundleEntryParts> toListOfEntries(FhirContext theContext, IBaseBundle theBundle) {
List<BundleEntryParts> retVal = new ArrayList<BundleEntryParts>();
RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle);
BaseRuntimeChildDefinition entryChild = def.getChildByName("entry");
List<IBase> entries = entryChild.getAccessor().getValues(theBundle);
BaseRuntimeElementCompositeDefinition<?> entryChildElem = (BaseRuntimeElementCompositeDefinition<?>) entryChild.getChildByName("entry");
BaseRuntimeChildDefinition resourceChild = entryChildElem.getChildByName("resource");
BaseRuntimeChildDefinition requestChild = entryChildElem.getChildByName("request");
BaseRuntimeElementCompositeDefinition<?> requestElem = (BaseRuntimeElementCompositeDefinition<?>) requestChild.getChildByName("request");
BaseRuntimeChildDefinition urlChild = requestElem.getChildByName("url");
BaseRuntimeChildDefinition methodChild = requestElem.getChildByName("method");
IBaseResource resource = null;
String url = null;
RequestTypeEnum requestType = null;
for (IBase nextEntry : entries) {
for (IBase next : resourceChild.getAccessor().getValues(nextEntry)) {
resource = (IBaseResource) next;
}
for (IBase nextRequest : requestChild.getAccessor().getValues(nextEntry)) {
for (IBase nextUrl : urlChild.getAccessor().getValues(nextRequest)) {
url = ((IPrimitiveType<?>)nextUrl).getValueAsString();
}
for (IBase nextUrl : methodChild.getAccessor().getValues(nextRequest)) {
String methodString = ((IPrimitiveType<?>)nextUrl).getValueAsString();
if (isNotBlank(methodString)) {
requestType = RequestTypeEnum.valueOf(methodString);
}
}
}
/*
* All 3 might be null - That's ok because we still want to know the
* order in the original bundle.
*/
retVal.add(new BundleEntryParts(requestType, url, resource));
}
return retVal;
}
/**
* Extract all of the resources from a given bundle
*/
public static List<IBaseResource> toListOfResources(FhirContext theContext, IBaseBundle theBundle) {
List<IBaseResource> retVal = new ArrayList<IBaseResource>();
RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle);
BaseRuntimeChildDefinition entryChild = def.getChildByName("entry");
List<IBase> entries = entryChild.getAccessor().getValues(theBundle);
BaseRuntimeElementCompositeDefinition<?> entryChildElem = (BaseRuntimeElementCompositeDefinition<?>) entryChild.getChildByName("entry");
BaseRuntimeChildDefinition resourceChild = entryChildElem.getChildByName("resource");
for (IBase nextEntry : entries) {
for (IBase next : resourceChild.getAccessor().getValues(nextEntry)) {
retVal.add((IBaseResource) next);
}
}
return retVal;
}
public static class BundleEntryParts
{
private final RequestTypeEnum myRequestType;
private final IBaseResource myResource;
private final String myUrl;
public BundleEntryParts(RequestTypeEnum theRequestType, String theUrl, IBaseResource theResource) {
super();
myRequestType = theRequestType;
myUrl = theUrl;
myResource = theResource;
}
public RequestTypeEnum getRequestType() {
return myRequestType;
}
public IBaseResource getResource() {
return myResource;
}
public String getUrl() {
return myUrl;
}
}
}