added attribute to Operation annotation (#4120)
* added attribute to Operation annotation * add find operation id * update readOperationDefinition method * add example to canonicalUrl * adding more examples
This commit is contained in:
parent
9d7829a404
commit
2de9b5aa03
|
@ -150,4 +150,14 @@ public @interface Operation {
|
||||||
*/
|
*/
|
||||||
boolean global() default false;
|
boolean global() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The canonical URL of the operation, e.g. "http://hl7.org/fhir/us/davinci-hrex/OperationDefinition/member-match|1.0.0"
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This may be specified with or without a version. e.g. @Operation(name = "$everything", canonicalUrl = "http://hl7.org/fhir/OperationDefinition/Patient-everything")
|
||||||
|
* or @Operation(name = "$member-match", canonicalUrl = "http://hl7.org/fhir/us/davinci-hrex/OperationDefinition/member-match|1.0.0")
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
String canonicalUrl() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 4116
|
||||||
|
jira: SMILE-5055
|
||||||
|
title: "Added new attribute for the @Operation annotation to define the operation's canonical URL. This canonical URL value will populate
|
||||||
|
the operation definition in the CapabilityStatement resource."
|
|
@ -66,7 +66,7 @@ public abstract class BaseJpaResourceProviderPatientR4 extends JpaResourceProvid
|
||||||
/**
|
/**
|
||||||
* Patient/123/$everything
|
* Patient/123/$everything
|
||||||
*/
|
*/
|
||||||
@Operation(name = JpaConstants.OPERATION_EVERYTHING, idempotent = true, bundleType = BundleTypeEnum.SEARCHSET)
|
@Operation(name = JpaConstants.OPERATION_EVERYTHING, canonicalUrl = "http://hl7.org/fhir/OperationDefinition/Patient-everything", idempotent = true, bundleType = BundleTypeEnum.SEARCHSET)
|
||||||
public IBundleProvider patientInstanceEverything(
|
public IBundleProvider patientInstanceEverything(
|
||||||
|
|
||||||
javax.servlet.http.HttpServletRequest theServletRequest,
|
javax.servlet.http.HttpServletRequest theServletRequest,
|
||||||
|
@ -129,7 +129,7 @@ public abstract class BaseJpaResourceProviderPatientR4 extends JpaResourceProvid
|
||||||
/**
|
/**
|
||||||
* /Patient/$everything
|
* /Patient/$everything
|
||||||
*/
|
*/
|
||||||
@Operation(name = JpaConstants.OPERATION_EVERYTHING, idempotent = true, bundleType = BundleTypeEnum.SEARCHSET)
|
@Operation(name = JpaConstants.OPERATION_EVERYTHING, canonicalUrl = "http://hl7.org/fhir/OperationDefinition/Patient-everything", idempotent = true, bundleType = BundleTypeEnum.SEARCHSET)
|
||||||
public IBundleProvider patientTypeEverything(
|
public IBundleProvider patientTypeEverything(
|
||||||
|
|
||||||
javax.servlet.http.HttpServletRequest theServletRequest,
|
javax.servlet.http.HttpServletRequest theServletRequest,
|
||||||
|
@ -197,7 +197,7 @@ public abstract class BaseJpaResourceProviderPatientR4 extends JpaResourceProvid
|
||||||
* Basic implementation matching by coverage id or by coverage identifier. Not matching by
|
* Basic implementation matching by coverage id or by coverage identifier. Not matching by
|
||||||
* Beneficiary (Patient) demographics in this version
|
* Beneficiary (Patient) demographics in this version
|
||||||
*/
|
*/
|
||||||
@Operation(name = ProviderConstants.OPERATION_MEMBER_MATCH, idempotent = false, returnParameters = {
|
@Operation(name = ProviderConstants.OPERATION_MEMBER_MATCH, canonicalUrl = "http://hl7.org/fhir/us/davinci-hrex/OperationDefinition/member-match", idempotent = false, returnParameters = {
|
||||||
@OperationParam(name = "MemberIdentifier", typeName = "string")
|
@OperationParam(name = "MemberIdentifier", typeName = "string")
|
||||||
})
|
})
|
||||||
public Parameters patientMemberMatch(
|
public Parameters patientMemberMatch(
|
||||||
|
|
|
@ -76,6 +76,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
private List<ReturnType> myReturnParams;
|
private List<ReturnType> myReturnParams;
|
||||||
private boolean myManualRequestMode;
|
private boolean myManualRequestMode;
|
||||||
private boolean myManualResponseMode;
|
private boolean myManualResponseMode;
|
||||||
|
private String myCanonicalUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor - This is the constructor that is called when binding a
|
* Constructor - This is the constructor that is called when binding a
|
||||||
|
@ -85,7 +86,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
Operation theAnnotation) {
|
Operation theAnnotation) {
|
||||||
this(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, theAnnotation.idempotent(), theAnnotation.deleteEnabled(), theAnnotation.name(), theAnnotation.type(), theAnnotation.typeName(), theAnnotation.returnParameters(),
|
this(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, theAnnotation.idempotent(), theAnnotation.deleteEnabled(), theAnnotation.name(), theAnnotation.type(), theAnnotation.typeName(), theAnnotation.returnParameters(),
|
||||||
theAnnotation.bundleType(), theAnnotation.global());
|
theAnnotation.bundleType(), theAnnotation.global());
|
||||||
|
myCanonicalUrl = theAnnotation.canonicalUrl();
|
||||||
myManualRequestMode = theAnnotation.manualRequest();
|
myManualRequestMode = theAnnotation.manualRequest();
|
||||||
myManualResponseMode = theAnnotation.manualResponse();
|
myManualResponseMode = theAnnotation.manualResponse();
|
||||||
}
|
}
|
||||||
|
@ -382,6 +383,10 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
return myManualRequestMode;
|
return myManualRequestMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCanonicalUrl() {
|
||||||
|
return myCanonicalUrl;
|
||||||
|
}
|
||||||
|
|
||||||
public static class ReturnType {
|
public static class ReturnType {
|
||||||
private int myMax;
|
private int myMax;
|
||||||
private int myMin;
|
private int myMin;
|
||||||
|
|
|
@ -20,7 +20,6 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServerConfiguration;
|
import ca.uhn.fhir.rest.server.RestfulServerConfiguration;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
|
||||||
import ca.uhn.fhir.rest.server.method.IParameter;
|
import ca.uhn.fhir.rest.server.method.IParameter;
|
||||||
import ca.uhn.fhir.rest.server.method.OperationMethodBinding;
|
import ca.uhn.fhir.rest.server.method.OperationMethodBinding;
|
||||||
import ca.uhn.fhir.rest.server.method.OperationMethodBinding.ReturnType;
|
import ca.uhn.fhir.rest.server.method.OperationMethodBinding.ReturnType;
|
||||||
|
@ -101,7 +100,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
||||||
private final IValidationSupport myValidationSupport;
|
private final IValidationSupport myValidationSupport;
|
||||||
private String myPublisher = "Not provided";
|
private String myPublisher = "Not provided";
|
||||||
private boolean myRestResourceRevIncludesEnabled = DEFAULT_REST_RESOURCE_REV_INCLUDES_ENABLED;
|
private boolean myRestResourceRevIncludesEnabled = DEFAULT_REST_RESOURCE_REV_INCLUDES_ENABLED;
|
||||||
|
private HashMap<String, String> operationCanonicalUrlToId = new HashMap<>();
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
|
@ -555,7 +554,14 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
||||||
private void populateOperation(RequestDetails theRequestDetails, FhirTerser theTerser, OperationMethodBinding theMethodBinding, String theOpName, IBase theOperation) {
|
private void populateOperation(RequestDetails theRequestDetails, FhirTerser theTerser, OperationMethodBinding theMethodBinding, String theOpName, IBase theOperation) {
|
||||||
String operationName = theMethodBinding.getName().substring(1);
|
String operationName = theMethodBinding.getName().substring(1);
|
||||||
theTerser.addElement(theOperation, "name", operationName);
|
theTerser.addElement(theOperation, "name", operationName);
|
||||||
theTerser.addElement(theOperation, "definition", createOperationUrl(theRequestDetails, theOpName));
|
String operationCanonicalUrl = theMethodBinding.getCanonicalUrl();
|
||||||
|
if (isNotBlank(operationCanonicalUrl)) {
|
||||||
|
theTerser.addElement(theOperation, "definition", operationCanonicalUrl);
|
||||||
|
operationCanonicalUrlToId.put(operationCanonicalUrl, theOpName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
theTerser.addElement(theOperation, "definition", createOperationUrl(theRequestDetails, theOpName));
|
||||||
|
}
|
||||||
if (isNotBlank(theMethodBinding.getDescription())) {
|
if (isNotBlank(theMethodBinding.getDescription())) {
|
||||||
theTerser.addElement(theOperation, "documentation", theMethodBinding.getDescription());
|
theTerser.addElement(theOperation, "documentation", theMethodBinding.getDescription());
|
||||||
}
|
}
|
||||||
|
@ -634,8 +640,8 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
||||||
}
|
}
|
||||||
RestfulServerConfiguration configuration = getServerConfiguration();
|
RestfulServerConfiguration configuration = getServerConfiguration();
|
||||||
Bindings bindings = configuration.provideBindings();
|
Bindings bindings = configuration.provideBindings();
|
||||||
|
String operationId = getOperationId(theId);
|
||||||
List<OperationMethodBinding> operationBindings = bindings.getOperationIdToBindings().get(theId.getIdPart());
|
List<OperationMethodBinding> operationBindings = bindings.getOperationIdToBindings().get(operationId);
|
||||||
if (operationBindings != null && !operationBindings.isEmpty()) {
|
if (operationBindings != null && !operationBindings.isEmpty()) {
|
||||||
return readOperationDefinitionForOperation(theRequestDetails, bindings, operationBindings);
|
return readOperationDefinitionForOperation(theRequestDetails, bindings, operationBindings);
|
||||||
}
|
}
|
||||||
|
@ -647,6 +653,13 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
||||||
throw new ResourceNotFoundException(Msg.code(1978) + theId);
|
throw new ResourceNotFoundException(Msg.code(1978) + theId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getOperationId(IIdType theId) {
|
||||||
|
if (operationCanonicalUrlToId.get(theId.getValue()) !=null ) {
|
||||||
|
return operationCanonicalUrlToId.get(theId.getValue());
|
||||||
|
}
|
||||||
|
return theId.getIdPart();
|
||||||
|
}
|
||||||
|
|
||||||
private IBaseResource readOperationDefinitionForNamedSearch(List<SearchMethodBinding> bindings) {
|
private IBaseResource readOperationDefinitionForNamedSearch(List<SearchMethodBinding> bindings) {
|
||||||
IBaseResource op = myContext.getResourceDefinition("OperationDefinition").newInstance();
|
IBaseResource op = myContext.getResourceDefinition("OperationDefinition").newInstance();
|
||||||
FhirTerser terser = myContext.newTerser();
|
FhirTerser terser = myContext.newTerser();
|
||||||
|
|
|
@ -1292,6 +1292,23 @@ public class ServerCapabilityStatementProviderR4Test {
|
||||||
assertThat(toOperationNames(groupResource.getOperation()),containsInAnyOrder("export", "export-poll-status"));
|
assertThat(toOperationNames(groupResource.getOperation()),containsInAnyOrder("export", "export-poll-status"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOperationReturningCanonicalUrl() throws Exception {
|
||||||
|
RestfulServer rs = new RestfulServer(myCtx);
|
||||||
|
rs.setProviders(new ProviderWithOperationReturningCanonicalUrl());
|
||||||
|
ServerCapabilityStatementProvider sc = new ServerCapabilityStatementProvider(rs) {};
|
||||||
|
rs.setServerConformanceProvider(sc);
|
||||||
|
rs.init(createServletConfig());
|
||||||
|
|
||||||
|
CapabilityStatement conformance = (CapabilityStatement) sc.getServerConformance(createHttpServletRequest(), createRequestDetails(rs));
|
||||||
|
assertEquals(2, conformance.getRest().get(0).getResource().size());
|
||||||
|
List<CapabilityStatementRestResourceOperationComponent> res = conformance.getRest().get(0).getResource().get(1).getOperation();
|
||||||
|
assertEquals(1, res.size());
|
||||||
|
CapabilityStatementRestResourceOperationComponent operationComponent = res.get(0);
|
||||||
|
assertEquals("everything", operationComponent.getName());
|
||||||
|
assertEquals("http://hl7.org/fhir/OperationDefinition/Patient-everything", operationComponent.getDefinition());
|
||||||
|
}
|
||||||
|
|
||||||
private List<String> toOperationIdParts(List<CapabilityStatementRestResourceOperationComponent> theOperation) {
|
private List<String> toOperationIdParts(List<CapabilityStatementRestResourceOperationComponent> theOperation) {
|
||||||
ArrayList<String> retVal = Lists.newArrayList();
|
ArrayList<String> retVal = Lists.newArrayList();
|
||||||
for (CapabilityStatementRestResourceOperationComponent next : theOperation) {
|
for (CapabilityStatementRestResourceOperationComponent next : theOperation) {
|
||||||
|
@ -1534,6 +1551,19 @@ public class ServerCapabilityStatementProviderR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ProviderWithOperationReturningCanonicalUrl implements IResourceProvider {
|
||||||
|
@Operation(name = "everything", canonicalUrl = "http://hl7.org/fhir/OperationDefinition/Patient-everything", idempotent = true)
|
||||||
|
public IBundleProvider everything(HttpServletRequest theServletRequest, @IdParam IdType theId,
|
||||||
|
@OperationParam(name = "someOpParam1") DateType theStart, @OperationParam(name = "someOpParam2") Encounter theEnd) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
|
return Patient.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static class ReadProvider {
|
public static class ReadProvider {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue