Populate Bundle.entry.fullUrl

This commit is contained in:
James Agnew 2015-09-02 13:42:59 -04:00
parent 6a2045fe12
commit ae177b52e8
4 changed files with 300 additions and 250 deletions

View File

@ -90,6 +90,7 @@ import ca.uhn.fhir.model.dstu2.valueset.AnswerFormatEnum;
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum; import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum; import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum; import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
import ca.uhn.fhir.model.dstu2.valueset.SearchEntryModeEnum;
import ca.uhn.fhir.model.primitive.DateDt; import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt; import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
@ -827,10 +828,21 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
p2.addName().addFamily("testSearchByIdentifierFamily01").addGiven("testSearchByIdentifierGiven02"); p2.addName().addFamily("testSearchByIdentifierFamily01").addGiven("testSearchByIdentifierGiven02");
ourClient.create().resource(p2).execute().getId(); ourClient.create().resource(p2).execute().getId();
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testSearchByIdentifier01")).encodedJson().prettyPrint().execute(); //@formatter:off
assertEquals(1, actual.size()); ca.uhn.fhir.model.dstu2.resource.Bundle actual = ourClient
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart()); .search()
assertEquals(BundleEntrySearchModeEnum.MATCH, actual.getEntries().get(0).getSearchMode().getValueAsEnum()); .forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testSearchByIdentifier01"))
.encodedJson()
.prettyPrint()
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
//@formatter:on
assertEquals(1, actual.getEntry().size());
assertEquals(ourServerBase + "/Patient/" + p1Id.getIdPart(), actual.getEntry().get(0).getFullUrl());
assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getId().getIdPart());
assertEquals(SearchEntryModeEnum.MATCH, actual.getEntry().get(0).getSearch().getModeElement().getValueAsEnum());
} }
@Test @Test

View File

@ -69,6 +69,7 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Dstu2BundleFactory.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Dstu2BundleFactory.class);
private Bundle myBundle; private Bundle myBundle;
private FhirContext myContext; private FhirContext myContext;
private String myBase;
public Dstu2BundleFactory(FhirContext theContext) { public Dstu2BundleFactory(FhirContext theContext) {
myContext = theContext; myContext = theContext;
@ -237,9 +238,7 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
} while (references.isEmpty() == false); } while (references.isEmpty() == false);
Entry entry = myBundle.addEntry().setResource(next); Entry entry = myBundle.addEntry().setResource(next);
if (next.getId().hasBaseUrl()) { populateBundleEntryFullUrl(next, entry);
entry.setFullUrl(next.getId().getValue());
}
BundleEntrySearchModeEnum searchMode = ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(next); BundleEntrySearchModeEnum searchMode = ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(next);
if (searchMode != null) { if (searchMode != null) {
@ -253,16 +252,28 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
for (IResource next : includedResources) { for (IResource next : includedResources) {
Entry entry = myBundle.addEntry(); Entry entry = myBundle.addEntry();
entry.setResource(next).getSearch().setMode(SearchEntryModeEnum.INCLUDE); entry.setResource(next).getSearch().setMode(SearchEntryModeEnum.INCLUDE);
if (next.getId().hasBaseUrl()) { populateBundleEntryFullUrl(next, entry);
entry.setFullUrl(next.getId().getValue());
}
} }
} }
private void populateBundleEntryFullUrl(IResource next, Entry entry) {
if (next.getId().hasBaseUrl()) {
entry.setFullUrl(next.getId().toVersionless().getValue());
} else {
if (isNotBlank(myBase) && next.getId().hasIdPart()) {
IdDt id = next.getId().toVersionless();
id = id.withServerBase(myBase, myContext.getResourceDefinition(next).getName());
entry.setFullUrl(id.getValue());
}
}
}
@Override @Override
public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl, Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType<Date> theLastUpdated) { public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl, Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType<Date> theLastUpdated) {
myBase = theServerBase;
if (myBundle.getId().isEmpty()) { if (myBundle.getId().isEmpty()) {
myBundle.setId(UUID.randomUUID().toString()); myBundle.setId(UUID.randomUUID().toString());
} }
@ -306,6 +317,8 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
@Override @Override
public void initializeBundleFromBundleProvider(RestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, public void initializeBundleFromBundleProvider(RestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl,
boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) { boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
myBase = theServerBase;
int numToReturn; int numToReturn;
String searchId = null; String searchId = null;
List<IBaseResource> resourceList; List<IBaseResource> resourceList;

View File

@ -19,7 +19,8 @@ package ca.uhn.fhir.rest.server.provider.dstu2hl7org;
* limitations under the License. * limitations under the License.
* #L% * #L%
*/ */
import static org.apache.commons.lang3.StringUtils.*; import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -131,23 +132,34 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
} while (references.isEmpty() == false); } while (references.isEmpty() == false);
BundleEntryComponent entry = myBundle.addEntry().setResource((Resource) next); BundleEntryComponent entry = myBundle.addEntry().setResource((Resource) next);
IdType nextId = (IdType) next.getIdElement(); populateBundleEntryFullUrl(next, entry);
if (isNotBlank(myBase) && isNotBlank(nextId.getResourceType())) {
entry.setFullUrlElement(nextId.withServerBase(myBase, nextId.getResourceType()));
}
} }
/* /*
* Actually add the resources to the bundle * Actually add the resources to the bundle
*/ */
for (IBaseResource next : includedResources) { for (IBaseResource next : includedResources) {
myBundle.addEntry().setResource((Resource) next).getSearch().setMode(SearchEntryMode.INCLUDE); BundleEntryComponent entry = myBundle.addEntry();
entry.setResource((Resource) next).getSearch().setMode(SearchEntryMode.INCLUDE);
populateBundleEntryFullUrl(next, entry);
}
}
private void populateBundleEntryFullUrl(IBaseResource next, BundleEntryComponent entry) {
if (next.getIdElement().hasBaseUrl()) {
entry.setFullUrl(next.getIdElement().toVersionless().getValue());
} else {
if (isNotBlank(myBase) && next.getIdElement().hasIdPart()) {
IIdType id = next.getIdElement().toVersionless();
id = id.withServerBase(myBase, myContext.getResourceDefinition(next).getName());
entry.setFullUrl(id.getValue());
}
} }
} }
@Override @Override
public void addResourcesToBundle(List<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes) { public void addResourcesToBundle(List<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase,
BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes) {
if (myBundle == null) { if (myBundle == null) {
myBundle = new Bundle(); myBundle = new Bundle();
} }
@ -237,7 +249,8 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
} }
@Override @Override
public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl, Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType<Date> theLastUpdated) { public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl,
Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType<Date> theLastUpdated) {
if (isBlank(myBundle.getId())) { if (isBlank(myBundle.getId())) {
myBundle.setId(UUID.randomUUID().toString()); myBundle.setId(UUID.randomUUID().toString());
@ -284,8 +297,10 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
} }
@Override @Override
public void initializeBundleFromBundleProvider(RestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, public void initializeBundleFromBundleProvider(RestfulServer theServer, IBundleProvider theResult,
Set<Include> theIncludes) { EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint,
int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
myBase = theServerBase;
int numToReturn; int numToReturn;
String searchId = null; String searchId = null;
List<IBaseResource> resourceList; List<IBaseResource> resourceList;
@ -322,7 +337,8 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
for (IBaseResource next : resourceList) { for (IBaseResource next : resourceList) {
if (next.getIdElement() == null || next.getIdElement().isEmpty()) { if (next.getIdElement() == null || next.getIdElement().isEmpty()) {
if (!(next instanceof OperationOutcome)) { if (!(next instanceof OperationOutcome)) {
throw new InternalErrorException("Server method returned resource of type[" + next.getClass().getSimpleName() + "] with no ID specified (IBaseResource#setId(IdDt) must be called)"); throw new InternalErrorException("Server method returned resource of type[" + next.getClass().getSimpleName()
+ "] with no ID specified (IBaseResource#setId(IdDt) must be called)");
} }
} }
} }
@ -337,7 +353,8 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
} }
addResourcesToBundle(resourceList, theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes); addResourcesToBundle(resourceList, theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType, theResult.getPublished()); addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, theResult.size(), theBundleType,
theResult.getPublished());
if (theServer.getPagingProvider() != null) { if (theServer.getPagingProvider() != null) {
int limit; int limit;
@ -346,18 +363,21 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
if (searchId != null) { if (searchId != null) {
if (theOffset + numToReturn < theResult.size()) { if (theOffset + numToReturn < theResult.size()) {
myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(RestfulServerUtils.createPagingLink(theIncludes, theServerBase, searchId, theOffset + numToReturn, numToReturn, theResponseEncoding, thePrettyPrint)); myBundle.addLink().setRelation(Constants.LINK_NEXT).setUrl(RestfulServerUtils.createPagingLink(theIncludes,
theServerBase, searchId, theOffset + numToReturn, numToReturn, theResponseEncoding, thePrettyPrint));
} }
if (theOffset > 0) { if (theOffset > 0) {
int start = Math.max(0, theOffset - limit); int start = Math.max(0, theOffset - limit);
myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(RestfulServerUtils.createPagingLink(theIncludes, theServerBase, searchId, start, limit, theResponseEncoding, thePrettyPrint)); myBundle.addLink().setRelation(Constants.LINK_PREVIOUS).setUrl(RestfulServerUtils.createPagingLink(
theIncludes, theServerBase, searchId, start, limit, theResponseEncoding, thePrettyPrint));
} }
} }
} }
} }
@Override @Override
public void initializeBundleFromResourceList(String theAuthor, List<? extends IBaseResource> theResources, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType) { public void initializeBundleFromResourceList(String theAuthor, List<? extends IBaseResource> theResources,
String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType) {
myBundle = new Bundle(); myBundle = new Bundle();
myBundle.setId(UUID.randomUUID().toString()); myBundle.setId(UUID.randomUUID().toString());
@ -382,7 +402,8 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
nextEntry.getRequest().setUrl(next.getIdElement().getValue()); nextEntry.getRequest().setUrl(next.getIdElement().getValue());
} else { } else {
String resourceType = myContext.getResourceDefinition(next).getName(); String resourceType = myContext.getResourceDefinition(next).getName();
nextEntry.getRequest().setUrl(new IdType(theServerBase, resourceType, next.getIdElement().getIdPart(), next.getIdElement().getVersionIdPart()).getValue()); nextEntry.getRequest().setUrl(new IdType(theServerBase, resourceType, next.getIdElement().getIdPart(),
next.getIdElement().getVersionIdPart()).getValue());
} }
} }
} }

View File

@ -155,6 +155,10 @@
Instance $meta operations on JPA server did not previously return the Instance $meta operations on JPA server did not previously return the
resource version and lastUpdated time resource version and lastUpdated time
</action> </action>
<action type="fix">
Server responses populate Bundle.entry.fullUrl if possible. Thanks
to Bill de Beaubien for reporting!
</action>
</release> </release>
<release version="1.1" date="2015-07-13"> <release version="1.1" date="2015-07-13">
<action type="add"> <action type="add">