
ca.uhn.fhir.rest.server.Dstu1BundleFactory Maven / Gradle / Ivy
package ca.uhn.fhir.rest.server;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2016 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 static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.ResourceReferenceInfo;
public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
private Bundle myBundle;
private FhirContext myContext;
public Dstu1BundleFactory(FhirContext theContext) {
myContext = theContext;
}
@Override
public void addResourcesToBundle(List theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set theIncludes) {
if (myBundle == null) {
myBundle = new Bundle();
}
List includedResources = new ArrayList();
Set addedResourceIds = new HashSet();
for (IBaseResource next : theResult) {
if (next.getIdElement().isEmpty() == false) {
addedResourceIds.add((IdDt) next.getIdElement());
}
}
for (IBaseResource nextBaseRes : theResult) {
IResource next = (IResource) nextBaseRes;
Set containedIds = new HashSet();
for (IResource nextContained : next.getContained().getContainedResources()) {
if (nextContained.getId().isEmpty() == false) {
containedIds.add(nextContained.getId().getValue());
}
}
List references = myContext.newTerser().getAllResourceReferences(next);
do {
List addedResourcesThisPass = new ArrayList();
for (ResourceReferenceInfo nextRefInfo : references) {
if (!theBundleInclusionRule.shouldIncludeReferencedResource(nextRefInfo, theIncludes))
continue;
IResource nextRes = (IResource) nextRefInfo.getResourceReference().getResource();
if (nextRes != null) {
if (nextRes.getId().hasIdPart()) {
if (containedIds.contains(nextRes.getId().getValue())) {
// Don't add contained IDs as top level resources
continue;
}
IdDt id = nextRes.getId();
if (id.hasResourceType() == false) {
String resName = myContext.getResourceDefinition(nextRes).getName();
id = id.withResourceType(resName);
}
if (!addedResourceIds.contains(id)) {
addedResourceIds.add(id);
addedResourcesThisPass.add(nextRes);
}
}
}
}
includedResources.addAll(addedResourcesThisPass);
// Linked resources may themselves have linked resources
references = new ArrayList();
for (IResource iResource : addedResourcesThisPass) {
List newReferences = myContext.newTerser().getAllResourceReferences(iResource);
references.addAll(newReferences);
}
} while (references.isEmpty() == false);
myBundle.addResource(next, myContext, theServerBase);
}
/*
* Actually add the resources to the bundle
*/
for (IResource next : includedResources) {
BundleEntry entry = myBundle.addResource(next, myContext, theServerBase);
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
if (entry.getSearchMode().isEmpty()) {
entry.getSearchMode().setValueAsEnum(BundleEntrySearchModeEnum.INCLUDE);
}
}
}
}
@Override
public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl, Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType theLastUpdated) {
if (myBundle.getAuthorName().isEmpty()) {
myBundle.getAuthorName().setValue(theAuthor);
}
if (myBundle.getUpdated().isEmpty() && isNotBlank(theLastUpdated.getValueAsString())) {
myBundle.getUpdated().setValueAsString(theLastUpdated.getValueAsString());
}
if (myBundle.getBundleId().isEmpty()) {
myBundle.getBundleId().setValue(UUID.randomUUID().toString());
}
if (myBundle.getLinkBase().isEmpty()) {
myBundle.getLinkBase().setValue(theServerBase);
}
if (myBundle.getLinkSelf().isEmpty()) {
myBundle.getLinkSelf().setValue(theCompleteUrl);
}
if (theBundleType != null && myBundle.getType().isEmpty()) {
myBundle.getType().setValueAsString(theBundleType.getCode());
}
if (myBundle.getTotalResults().isEmpty() && theTotalResults != null) {
myBundle.getTotalResults().setValue(theTotalResults);
}
}
@Override
public Bundle getDstu1Bundle() {
return myBundle;
}
@Override
public IResource getResourceBundle() {
return null;
}
@Override
public void initializeBundleFromBundleProvider(IRestfulServer> theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl,
boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set theIncludes) {
int numToReturn;
String searchId = null;
List resourceList;
if (theServer.getPagingProvider() == null) {
numToReturn = theResult.size();
resourceList = theResult.getResources(0, numToReturn);
RestfulServerUtils.validateResourceListNotNull(resourceList);
} else {
IPagingProvider pagingProvider = theServer.getPagingProvider();
if (theLimit == null) {
numToReturn = pagingProvider.getDefaultPageSize();
} else {
numToReturn = Math.min(pagingProvider.getMaximumPageSize(), theLimit);
}
numToReturn = Math.min(numToReturn, theResult.size() - theOffset);
resourceList = theResult.getResources(theOffset, numToReturn + theOffset);
RestfulServerUtils.validateResourceListNotNull(resourceList);
if (theSearchId != null) {
searchId = theSearchId;
} else {
if (theResult.size() > numToReturn) {
searchId = pagingProvider.storeResultList(theResult);
Validate.notNull(searchId, "Paging provider returned null searchId");
}
}
}
for (IBaseResource next : resourceList) {
if (next.getIdElement() == null || next.getIdElement().isEmpty()) {
if (!(next instanceof BaseOperationOutcome)) {
throw new InternalErrorException("Server method returned resource of type[" + next.getClass().getSimpleName() + "] with no ID specified (IResource#setId(IdDt) must be called)");
}
}
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
addProfileIfNeeded(theServer, theServerBase, next);
}
}
addResourcesToBundle(new ArrayList(resourceList), theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType, theResult.getPublished());
if (theServer.getPagingProvider() != null) {
int limit;
limit = theLimit != null ? theLimit : theServer.getPagingProvider().getDefaultPageSize();
limit = Math.min(limit, theServer.getPagingProvider().getMaximumPageSize());
if (searchId != null) {
if (theOffset + numToReturn < theResult.size()) {
myBundle.getLinkNext()
.setValue(RestfulServerUtils.createPagingLink(theIncludes, theServerBase, searchId, theOffset + numToReturn, numToReturn, theResponseEncoding, thePrettyPrint, theBundleType));
}
if (theOffset > 0) {
int start = Math.max(0, theOffset - limit);
myBundle.getLinkPrevious().setValue(RestfulServerUtils.createPagingLink(theIncludes, theServerBase, searchId, start, limit, theResponseEncoding, thePrettyPrint, theBundleType));
}
}
}
}
private void addProfileIfNeeded(IRestfulServer> theServer, String theServerBase, IBaseResource nextRes) {
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardType()) {
TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get((IResource) nextRes);
if (tl == null) {
tl = new TagList();
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) nextRes, tl);
}
RuntimeResourceDefinition nextDef = myContext.getResourceDefinition(nextRes);
String profile = nextDef.getResourceProfile(theServerBase);
if (isNotBlank(profile)) {
tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
}
}
}
@Override
public void initializeBundleFromResourceList(String theAuthor, List extends IBaseResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults,
BundleTypeEnum theBundleType) {
myBundle = new Bundle();
myBundle.getAuthorName().setValue(theAuthor);
myBundle.getBundleId().setValue(UUID.randomUUID().toString());
myBundle.getLinkBase().setValue(theServerBase);
myBundle.getLinkSelf().setValue(theCompleteUrl);
myBundle.getType().setValueAsEnum(theBundleType);
List includedResources = new ArrayList();
Set addedResourceIds = new HashSet();
for (IBaseResource next : theResult) {
if (next.getIdElement().isEmpty() == false) {
addedResourceIds.add(next.getIdElement());
}
}
for (IBaseResource nextRes : theResult) {
IResource next = (IResource) nextRes;
Set containedIds = new HashSet();
for (IResource nextContained : next.getContained().getContainedResources()) {
if (nextContained.getId().isEmpty() == false) {
containedIds.add(nextContained.getId().getValue());
}
}
List references = myContext.newTerser().getAllPopulatedChildElementsOfType(next, BaseResourceReferenceDt.class);
do {
List addedResourcesThisPass = new ArrayList();
for (BaseResourceReferenceDt nextRef : references) {
IBaseResource nextRefRes = nextRef.getResource();
if (nextRefRes != null) {
if (nextRefRes.getIdElement().hasIdPart()) {
if (containedIds.contains(nextRefRes.getIdElement().getValue())) {
// Don't add contained IDs as top level resources
continue;
}
IIdType id = nextRefRes.getIdElement();
if (id.hasResourceType() == false) {
String resName = myContext.getResourceDefinition(nextRefRes).getName();
id = id.withResourceType(resName);
}
if (!addedResourceIds.contains(id)) {
addedResourceIds.add(id);
addedResourcesThisPass.add(nextRefRes);
}
}
}
}
// Linked resources may themselves have linked resources
references = new ArrayList();
for (IBaseResource iResource : addedResourcesThisPass) {
List newReferences = myContext.newTerser().getAllPopulatedChildElementsOfType(iResource, BaseResourceReferenceDt.class);
references.addAll(newReferences);
}
includedResources.addAll(addedResourcesThisPass);
} while (references.isEmpty() == false);
myBundle.addResource(next, myContext, theServerBase);
}
/*
* Actually add the resources to the bundle
*/
for (IBaseResource next : includedResources) {
BundleEntry entry = myBundle.addResource((IResource) next, myContext, theServerBase);
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
if (entry.getSearchMode().isEmpty()) {
entry.getSearchMode().setValueAsEnum(BundleEntrySearchModeEnum.INCLUDE);
}
}
}
myBundle.getTotalResults().setValue(theTotalResults);
}
@Override
public void initializeWithBundleResource(IBaseResource theResource) {
throw new UnsupportedOperationException("DSTU1 server doesn't support resource style bundles");
}
@Override
public List toListOfResources() {
return new ArrayList(myBundle.toListOfResources());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy