Correctly handle "special" search params in CS (#1569)
* Correctly handle "special" search params in CS * Add another test
This commit is contained in:
parent
84803a02ef
commit
9c852283e9
|
@ -19,24 +19,25 @@ package ca.uhn.fhir.jpa.provider.r4;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.CapabilityStatement.*;
|
||||
import org.hl7.fhir.r4.model.Enumerations.SearchParamType;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
import ca.uhn.fhir.util.ExtensionConstants;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.CapabilityStatement.*;
|
||||
import org.hl7.fhir.r4.model.Enumerations.SearchParamType;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
@ -50,17 +51,17 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
private boolean myIncludeResourceCounts;
|
||||
private RestfulServer myRestfulServer;
|
||||
private IFhirSystemDao<Bundle, Meta> mySystemDao;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@CoverageIgnore
|
||||
public JpaConformanceProviderR4(){
|
||||
public JpaConformanceProviderR4() {
|
||||
super();
|
||||
super.setCache(false);
|
||||
setIncludeResourceCounts(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -94,7 +95,7 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
for (CapabilityStatementRestResourceComponent nextResource : nextRest.getResource()) {
|
||||
|
||||
nextResource.setVersioning(ResourceVersionPolicy.VERSIONEDUPDATE);
|
||||
|
||||
|
||||
ConditionalDeleteStatus conditionalDelete = nextResource.getConditionalDelete();
|
||||
if (conditionalDelete == ConditionalDeleteStatus.MULTIPLE && myDaoConfig.isAllowMultipleDelete() == false) {
|
||||
nextResource.setConditionalDelete(ConditionalDeleteStatus.SINGLE);
|
||||
|
@ -109,7 +110,7 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
nextResource.getSearchParam().clear();
|
||||
String resourceName = nextResource.getType();
|
||||
RuntimeResourceDefinition resourceDef = myRestfulServer.getFhirContext().getResourceDefinition(resourceName);
|
||||
Collection<RuntimeSearchParam> searchParams = mySearchParamRegistry.getSearchParamsByResourceType(resourceDef);
|
||||
Collection<RuntimeSearchParam> searchParams = mySearchParamRegistry.getSearchParamsByResourceType(resourceDef);
|
||||
for (RuntimeSearchParam runtimeSp : searchParams) {
|
||||
CapabilityStatementRestResourceSearchParamComponent confSp = nextResource.addSearchParam();
|
||||
|
||||
|
@ -117,37 +118,40 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
confSp.setDocumentation(runtimeSp.getDescription());
|
||||
confSp.setDefinition(runtimeSp.getUri());
|
||||
switch (runtimeSp.getParamType()) {
|
||||
case COMPOSITE:
|
||||
confSp.setType(SearchParamType.COMPOSITE);
|
||||
break;
|
||||
case DATE:
|
||||
confSp.setType(SearchParamType.DATE);
|
||||
break;
|
||||
case NUMBER:
|
||||
confSp.setType(SearchParamType.NUMBER);
|
||||
break;
|
||||
case QUANTITY:
|
||||
confSp.setType(SearchParamType.QUANTITY);
|
||||
break;
|
||||
case REFERENCE:
|
||||
confSp.setType(SearchParamType.REFERENCE);
|
||||
break;
|
||||
case STRING:
|
||||
confSp.setType(SearchParamType.STRING);
|
||||
break;
|
||||
case TOKEN:
|
||||
confSp.setType(SearchParamType.TOKEN);
|
||||
break;
|
||||
case URI:
|
||||
confSp.setType(SearchParamType.URI);
|
||||
break;
|
||||
case HAS:
|
||||
// Shouldn't happen
|
||||
break;
|
||||
case COMPOSITE:
|
||||
confSp.setType(SearchParamType.COMPOSITE);
|
||||
break;
|
||||
case DATE:
|
||||
confSp.setType(SearchParamType.DATE);
|
||||
break;
|
||||
case NUMBER:
|
||||
confSp.setType(SearchParamType.NUMBER);
|
||||
break;
|
||||
case QUANTITY:
|
||||
confSp.setType(SearchParamType.QUANTITY);
|
||||
break;
|
||||
case REFERENCE:
|
||||
confSp.setType(SearchParamType.REFERENCE);
|
||||
break;
|
||||
case STRING:
|
||||
confSp.setType(SearchParamType.STRING);
|
||||
break;
|
||||
case TOKEN:
|
||||
confSp.setType(SearchParamType.TOKEN);
|
||||
break;
|
||||
case URI:
|
||||
confSp.setType(SearchParamType.URI);
|
||||
break;
|
||||
case SPECIAL:
|
||||
confSp.setType(SearchParamType.SPECIAL);
|
||||
break;
|
||||
case HAS:
|
||||
// Shouldn't happen
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,7 +165,7 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
}
|
||||
|
||||
massage(retVal);
|
||||
|
||||
|
||||
retVal.getImplementation().setDescription(myImplementationDescription);
|
||||
myCachedValue = retVal;
|
||||
return retVal;
|
||||
|
@ -170,7 +174,11 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
public boolean isIncludeResourceCounts() {
|
||||
return myIncludeResourceCounts;
|
||||
}
|
||||
|
||||
|
||||
public void setIncludeResourceCounts(boolean theIncludeResourceCounts) {
|
||||
myIncludeResourceCounts = theIncludeResourceCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
*/
|
||||
|
@ -187,10 +195,6 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
myImplementationDescription = theImplDesc;
|
||||
}
|
||||
|
||||
public void setIncludeResourceCounts(boolean theIncludeResourceCounts) {
|
||||
myIncludeResourceCounts = theIncludeResourceCounts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRestfulServer(RestfulServer theRestfulServer) {
|
||||
this.myRestfulServer = theRestfulServer;
|
||||
|
|
|
@ -51,16 +51,16 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
private boolean myIncludeResourceCounts;
|
||||
private RestfulServer myRestfulServer;
|
||||
private IFhirSystemDao<Bundle, Meta> mySystemDao;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@CoverageIgnore
|
||||
public JpaConformanceProviderR5(){
|
||||
public JpaConformanceProviderR5() {
|
||||
super();
|
||||
setIncludeResourceCounts(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -93,7 +93,7 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
for (CapabilityStatementRestResourceComponent nextResource : nextRest.getResource()) {
|
||||
|
||||
nextResource.setVersioning(ResourceVersionPolicy.VERSIONEDUPDATE);
|
||||
|
||||
|
||||
ConditionalDeleteStatus conditionalDelete = nextResource.getConditionalDelete();
|
||||
if (conditionalDelete == ConditionalDeleteStatus.MULTIPLE && myDaoConfig.isAllowMultipleDelete() == false) {
|
||||
nextResource.setConditionalDelete(ConditionalDeleteStatus.SINGLE);
|
||||
|
@ -108,7 +108,7 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
nextResource.getSearchParam().clear();
|
||||
String resourceName = nextResource.getType();
|
||||
RuntimeResourceDefinition resourceDef = myRestfulServer.getFhirContext().getResourceDefinition(resourceName);
|
||||
Collection<RuntimeSearchParam> searchParams = mySearchParamRegistry.getSearchParamsByResourceType(resourceDef);
|
||||
Collection<RuntimeSearchParam> searchParams = mySearchParamRegistry.getSearchParamsByResourceType(resourceDef);
|
||||
for (RuntimeSearchParam runtimeSp : searchParams) {
|
||||
CapabilityStatementRestResourceSearchParamComponent confSp = nextResource.addSearchParam();
|
||||
|
||||
|
@ -116,37 +116,40 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
confSp.setDocumentation(runtimeSp.getDescription());
|
||||
confSp.setDefinition(runtimeSp.getUri());
|
||||
switch (runtimeSp.getParamType()) {
|
||||
case COMPOSITE:
|
||||
confSp.setType(SearchParamType.COMPOSITE);
|
||||
break;
|
||||
case DATE:
|
||||
confSp.setType(SearchParamType.DATE);
|
||||
break;
|
||||
case NUMBER:
|
||||
confSp.setType(SearchParamType.NUMBER);
|
||||
break;
|
||||
case QUANTITY:
|
||||
confSp.setType(SearchParamType.QUANTITY);
|
||||
break;
|
||||
case REFERENCE:
|
||||
confSp.setType(SearchParamType.REFERENCE);
|
||||
break;
|
||||
case STRING:
|
||||
confSp.setType(SearchParamType.STRING);
|
||||
break;
|
||||
case TOKEN:
|
||||
confSp.setType(SearchParamType.TOKEN);
|
||||
break;
|
||||
case URI:
|
||||
confSp.setType(SearchParamType.URI);
|
||||
break;
|
||||
case HAS:
|
||||
// Shouldn't happen
|
||||
break;
|
||||
case COMPOSITE:
|
||||
confSp.setType(SearchParamType.COMPOSITE);
|
||||
break;
|
||||
case DATE:
|
||||
confSp.setType(SearchParamType.DATE);
|
||||
break;
|
||||
case NUMBER:
|
||||
confSp.setType(SearchParamType.NUMBER);
|
||||
break;
|
||||
case QUANTITY:
|
||||
confSp.setType(SearchParamType.QUANTITY);
|
||||
break;
|
||||
case REFERENCE:
|
||||
confSp.setType(SearchParamType.REFERENCE);
|
||||
break;
|
||||
case STRING:
|
||||
confSp.setType(SearchParamType.STRING);
|
||||
break;
|
||||
case TOKEN:
|
||||
confSp.setType(SearchParamType.TOKEN);
|
||||
break;
|
||||
case URI:
|
||||
confSp.setType(SearchParamType.URI);
|
||||
break;
|
||||
case SPECIAL:
|
||||
confSp.setType(SearchParamType.SPECIAL);
|
||||
break;
|
||||
case HAS:
|
||||
// Shouldn't happen
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +163,7 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
}
|
||||
|
||||
massage(retVal);
|
||||
|
||||
|
||||
retVal.getImplementation().setDescription(myImplementationDescription);
|
||||
myCachedValue = retVal;
|
||||
return retVal;
|
||||
|
@ -169,7 +172,11 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
public boolean isIncludeResourceCounts() {
|
||||
return myIncludeResourceCounts;
|
||||
}
|
||||
|
||||
|
||||
public void setIncludeResourceCounts(boolean theIncludeResourceCounts) {
|
||||
myIncludeResourceCounts = theIncludeResourceCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
*/
|
||||
|
@ -186,10 +193,6 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
myImplementationDescription = theImplDesc;
|
||||
}
|
||||
|
||||
public void setIncludeResourceCounts(boolean theIncludeResourceCounts) {
|
||||
myIncludeResourceCounts = theIncludeResourceCounts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRestfulServer(RestfulServer theRestfulServer) {
|
||||
this.myRestfulServer = theRestfulServer;
|
||||
|
|
|
@ -195,6 +195,11 @@ public class ResourceReindexingSvcImpl implements IResourceReindexingSvc {
|
|||
mySchedulerService.scheduleFixedDelay(10 * DateUtils.MILLIS_PER_SECOND, true, jobDetail);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ReentrantLock getIndexingLockForUnitTest() {
|
||||
return myIndexingLock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(Transactional.TxType.NEVER)
|
||||
public Integer runReindexingPass() {
|
||||
|
|
|
@ -68,7 +68,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
|
|||
private static SubscriptionMatcherInterceptor ourSubscriptionMatcherInterceptor;
|
||||
protected static Server ourServer;
|
||||
protected IGenericClient ourClient;
|
||||
ResourceCountCache ourResourceCountsCache;
|
||||
ResourceCountCache myResourceCountsCache;
|
||||
private TerminologyUploaderProvider myTerminologyUploaderProvider;
|
||||
private boolean ourRestHookSubscriptionInterceptorRequested;
|
||||
|
||||
|
@ -93,6 +93,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
|
|||
myFhirCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
myFhirCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
|
||||
myFhirCtx.setParserErrorHandler(new StrictErrorHandler());
|
||||
myResourceCountsCache = (ResourceCountCache) myAppCtx.getBean("myResourceCountsCache");
|
||||
|
||||
if (ourServer == null) {
|
||||
ourRestServer = new RestfulServer(myFhirCtx);
|
||||
|
@ -113,7 +114,6 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
|
|||
ourRestServer.setServerConformanceProvider(confProvider);
|
||||
|
||||
ourPagingProvider = myAppCtx.getBean(DatabaseBackedPagingProvider.class);
|
||||
ourResourceCountsCache = (ResourceCountCache) myAppCtx.getBean("myResourceCountsCache");
|
||||
|
||||
Server server = new Server(0);
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package ca.uhn.fhir.jpa.provider.r4;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.util.ExtensionConstants;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -13,6 +16,7 @@ import org.hl7.fhir.r4.model.Extension;
|
|||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -25,6 +29,29 @@ public class ServerR4Test extends BaseResourceProviderR4Test {
|
|||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerR4Test.class);
|
||||
|
||||
@Autowired
|
||||
private IFhirResourceDao<CapabilityStatement> myCapabilityStatementDao;
|
||||
|
||||
@Test
|
||||
public void testCapabilityStatementValidates() throws IOException {
|
||||
HttpGet get = new HttpGet(ourServerBase + "/metadata?_pretty=true&_format=json");
|
||||
try (CloseableHttpResponse resp = ourHttpClient.execute(get)) {
|
||||
assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
|
||||
ourLog.info(respString);
|
||||
|
||||
CapabilityStatement cs = myFhirCtx.newJsonParser().parseResource(CapabilityStatement.class, respString);
|
||||
|
||||
try {
|
||||
myCapabilityStatementDao.validate(cs, null, respString, EncodingEnum.JSON, null, null, null);
|
||||
} catch (PreconditionFailedException e) {
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See #519
|
||||
|
@ -71,7 +98,7 @@ public class ServerR4Test extends BaseResourceProviderR4Test {
|
|||
* Initial fetch after a clear should return
|
||||
* no results
|
||||
*/
|
||||
ourResourceCountsCache.clear();
|
||||
myResourceCountsCache.clear();
|
||||
|
||||
CapabilityStatement capabilityStatement = ourClient
|
||||
.capabilities()
|
||||
|
@ -93,7 +120,7 @@ public class ServerR4Test extends BaseResourceProviderR4Test {
|
|||
* Now run a background pass (the update
|
||||
* method is called by the scheduler normally)
|
||||
*/
|
||||
ourResourceCountsCache.update();
|
||||
myResourceCountsCache.update();
|
||||
|
||||
capabilityStatement = ourClient
|
||||
.capabilities()
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
package ca.uhn.fhir.jpa.provider.r5;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.util.ExtensionConstants;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
import org.hl7.fhir.r5.model.Patient;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ServerR5Test extends BaseResourceProviderR5Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerR5Test.class);
|
||||
|
||||
@Autowired
|
||||
private IFhirResourceDao<CapabilityStatement> myCapabilityStatementDao;
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testCapabilityStatementValidates() throws IOException {
|
||||
HttpGet get = new HttpGet(ourServerBase + "/metadata?_pretty=true&_format=json");
|
||||
try (CloseableHttpResponse resp = ourHttpClient.execute(get)) {
|
||||
assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
|
||||
ourLog.info(respString);
|
||||
|
||||
CapabilityStatement cs = myFhirCtx.newJsonParser().parseResource(CapabilityStatement.class, respString);
|
||||
|
||||
try {
|
||||
myCapabilityStatementDao.validate(cs, null, respString, EncodingEnum.JSON, null, null, null);
|
||||
} catch (PreconditionFailedException e) {
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See #519
|
||||
*/
|
||||
@Test
|
||||
public void saveIdParamOnlyAppearsOnce() throws IOException {
|
||||
HttpGet get = new HttpGet(ourServerBase + "/metadata?_pretty=true&_format=xml");
|
||||
CloseableHttpResponse resp = ourHttpClient.execute(get);
|
||||
try {
|
||||
ourLog.info(resp.toString());
|
||||
assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||
|
||||
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(respString);
|
||||
|
||||
CapabilityStatement cs = myFhirCtx.newXmlParser().parseResource(CapabilityStatement.class, respString);
|
||||
|
||||
for (CapabilityStatementRestResourceComponent nextResource : cs.getRest().get(0).getResource()) {
|
||||
ourLog.info("Testing resource: " + nextResource.getType());
|
||||
Set<String> sps = new HashSet<String>();
|
||||
for (CapabilityStatementRestResourceSearchParamComponent nextSp : nextResource.getSearchParam()) {
|
||||
if (sps.add(nextSp.getName()) == false) {
|
||||
fail("Duplicate search parameter " + nextSp.getName() + " for resource " + nextResource.getType());
|
||||
}
|
||||
}
|
||||
|
||||
if (!sps.contains("_id")) {
|
||||
fail("No search parameter _id for resource " + nextResource.getType());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(resp.getEntity().getContent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMetadataIncludesResourceCounts() {
|
||||
Patient p = new Patient();
|
||||
p.setActive(true);
|
||||
ourClient.create().resource(p).execute();
|
||||
|
||||
/*
|
||||
* Initial fetch after a clear should return
|
||||
* no results
|
||||
*/
|
||||
myResourceCountsCache.clear();
|
||||
|
||||
CapabilityStatement capabilityStatement = ourClient
|
||||
.capabilities()
|
||||
.ofType(CapabilityStatement.class)
|
||||
.execute();
|
||||
|
||||
Extension patientCountExt = capabilityStatement
|
||||
.getRest()
|
||||
.get(0)
|
||||
.getResource()
|
||||
.stream()
|
||||
.filter(t -> t.getType().equals("Patient"))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new InternalErrorException("No patient"))
|
||||
.getExtensionByUrl(ExtensionConstants.CONF_RESOURCE_COUNT);
|
||||
assertNull(patientCountExt);
|
||||
|
||||
/*
|
||||
* Now run a background pass (the update
|
||||
* method is called by the scheduler normally)
|
||||
*/
|
||||
myResourceCountsCache.update();
|
||||
|
||||
capabilityStatement = ourClient
|
||||
.capabilities()
|
||||
.ofType(CapabilityStatement.class)
|
||||
.execute();
|
||||
|
||||
patientCountExt = capabilityStatement
|
||||
.getRest()
|
||||
.get(0)
|
||||
.getResource()
|
||||
.stream()
|
||||
.filter(t -> t.getType().equals("Patient"))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new InternalErrorException("No patient"))
|
||||
.getExtensionByUrl(ExtensionConstants.CONF_RESOURCE_COUNT);
|
||||
assertEquals("1", patientCountExt.getValueAsPrimitive().getValueAsString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
}
|
|
@ -26,6 +26,8 @@ import org.springframework.data.domain.SliceImpl;
|
|||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -94,6 +96,17 @@ public class ResourceReindexingSvcImplTest extends BaseJpaTest {
|
|||
mySvc.start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoParallelReindexing() throws InterruptedException {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
new Thread(()->{
|
||||
mySvc.getIndexingLockForUnitTest().lock();
|
||||
latch.countDown();
|
||||
}).start();
|
||||
latch.await(10, TimeUnit.SECONDS);
|
||||
mySvc.runReindexingPass();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReindexPassOnlyReturnsValuesAtLowThreshold() {
|
||||
mockNothingToExpunge();
|
||||
|
|
|
@ -9,7 +9,10 @@ import ca.uhn.fhir.rest.annotation.Metadata;
|
|||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.*;
|
||||
import ca.uhn.fhir.rest.server.Bindings;
|
||||
import ca.uhn.fhir.rest.server.IServerConformanceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerConfiguration;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.method.*;
|
||||
import ca.uhn.fhir.rest.server.method.SearchParameter;
|
||||
|
@ -113,7 +116,6 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
|||
}
|
||||
|
||||
|
||||
|
||||
private DateTimeType conformanceDate(RequestDetails theRequestDetails) {
|
||||
IPrimitiveType<Date> buildDate = getServerConfiguration(theRequestDetails).getConformanceDate();
|
||||
if (buildDate != null && buildDate.getValue() != null) {
|
||||
|
@ -127,7 +129,6 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of the "publisher" that will be placed in the generated conformance statement. As this is a mandatory element, the value should not be null (although this is not enforced). The
|
||||
* value defaults to "Not provided" but may be set to null, which will cause this element to be omitted.
|
||||
|
@ -194,47 +195,46 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
|||
// Map<String, CapabilityStatement.RestResourceSearchParam> nameToSearchParam = new HashMap<String,
|
||||
// CapabilityStatement.RestResourceSearchParam>();
|
||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
||||
if (nextMethodBinding.getRestOperationType() != null) {
|
||||
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||
if (resOpCode != null) {
|
||||
TypeRestfulInteraction resOp;
|
||||
try {
|
||||
resOp = TypeRestfulInteraction.fromCode(resOpCode);
|
||||
} catch (Exception e) {
|
||||
resOp = null;
|
||||
nextMethodBinding.getRestOperationType();
|
||||
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||
if (resOpCode != null) {
|
||||
TypeRestfulInteraction resOp;
|
||||
try {
|
||||
resOp = TypeRestfulInteraction.fromCode(resOpCode);
|
||||
} catch (Exception e) {
|
||||
resOp = null;
|
||||
}
|
||||
if (resOp != null) {
|
||||
if (resourceOps.contains(resOp) == false) {
|
||||
resourceOps.add(resOp);
|
||||
resource.addInteraction().setCode(resOp);
|
||||
}
|
||||
if (resOp != null) {
|
||||
if ("vread".equals(resOpCode)) {
|
||||
// vread implies read
|
||||
resOp = TypeRestfulInteraction.READ;
|
||||
if (resourceOps.contains(resOp) == false) {
|
||||
resourceOps.add(resOp);
|
||||
resource.addInteraction().setCode(resOp);
|
||||
}
|
||||
if ("vread".equals(resOpCode)) {
|
||||
// vread implies read
|
||||
resOp = TypeRestfulInteraction.READ;
|
||||
if (resourceOps.contains(resOp) == false) {
|
||||
resourceOps.add(resOp);
|
||||
resource.addInteraction().setCode(resOp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nextMethodBinding.isSupportsConditional()) {
|
||||
switch (resOp) {
|
||||
case CREATE:
|
||||
resource.setConditionalCreate(true);
|
||||
break;
|
||||
case DELETE:
|
||||
if (nextMethodBinding.isSupportsConditionalMultiple()) {
|
||||
resource.setConditionalDelete(ConditionalDeleteStatus.MULTIPLE);
|
||||
} else {
|
||||
resource.setConditionalDelete(ConditionalDeleteStatus.SINGLE);
|
||||
}
|
||||
break;
|
||||
case UPDATE:
|
||||
resource.setConditionalUpdate(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (nextMethodBinding.isSupportsConditional()) {
|
||||
switch (resOp) {
|
||||
case CREATE:
|
||||
resource.setConditionalCreate(true);
|
||||
break;
|
||||
case DELETE:
|
||||
if (nextMethodBinding.isSupportsConditionalMultiple()) {
|
||||
resource.setConditionalDelete(ConditionalDeleteStatus.MULTIPLE);
|
||||
} else {
|
||||
resource.setConditionalDelete(ConditionalDeleteStatus.SINGLE);
|
||||
}
|
||||
break;
|
||||
case UPDATE:
|
||||
resource.setConditionalUpdate(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -315,28 +315,18 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
|||
}
|
||||
sortSearchParameters(searchParameters);
|
||||
if (!searchParameters.isEmpty()) {
|
||||
// boolean allOptional = searchParameters.get(0).isRequired() == false;
|
||||
//
|
||||
// OperationDefinition query = null;
|
||||
// if (!allOptional) {
|
||||
// RestOperation operation = rest.addOperation();
|
||||
// query = new OperationDefinition();
|
||||
// operation.setDefinition(new ResourceReferenceDt(query));
|
||||
// query.getDescriptionElement().setValue(searchMethodBinding.getDescription());
|
||||
// query.addUndeclaredExtension(false, ExtensionConstants.QUERY_RETURN_TYPE, new CodeDt(resourceName));
|
||||
// for (String nextInclude : searchMethodBinding.getIncludes()) {
|
||||
// query.addUndeclaredExtension(false, ExtensionConstants.QUERY_ALLOWED_INCLUDE, new StringDt(nextInclude));
|
||||
// }
|
||||
// }
|
||||
|
||||
for (SearchParameter nextParameter : searchParameters) {
|
||||
|
||||
if (nextParameter.getParamType() == null) {
|
||||
ourLog.warn("SearchParameter {}:{} does not declare a type - Not exporting in CapabilityStatement", def.getName(), nextParameter.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextParamName = nextParameter.getName();
|
||||
|
||||
String chain = null;
|
||||
String nextParamUnchainedName = nextParamName;
|
||||
if (nextParamName.contains(".")) {
|
||||
chain = nextParamName.substring(nextParamName.indexOf('.') + 1);
|
||||
nextParamUnchainedName = nextParamName.substring(0, nextParamName.indexOf('.'));
|
||||
}
|
||||
|
||||
|
@ -352,45 +342,18 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
CapabilityStatementRestResourceSearchParamComponent param = resource.addSearchParam();
|
||||
String typeCode = nextParameter.getParamType().getCode();
|
||||
param.getTypeElement().setValueAsString(typeCode);
|
||||
param.setName(nextParamUnchainedName);
|
||||
|
||||
// if (StringUtils.isNotBlank(chain)) {
|
||||
// param.addChain(chain);
|
||||
// }
|
||||
//
|
||||
// if (nextParameter.getParamType() == RestSearchParameterTypeEnum.REFERENCE) {
|
||||
// for (String nextWhitelist : new TreeSet<String>(nextParameter.getQualifierWhitelist())) {
|
||||
// if (nextWhitelist.startsWith(".")) {
|
||||
// param.addChain(nextWhitelist.substring(1));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
param.setDocumentation(nextParamDescription);
|
||||
if (nextParameter.getParamType() != null) {
|
||||
param.getTypeElement().setValueAsString(nextParameter.getParamType().getCode());
|
||||
}
|
||||
for (Class<? extends IBaseResource> nextTarget : nextParameter.getDeclaredTypes()) {
|
||||
RuntimeResourceDefinition targetDef = getServerConfiguration(theRequestDetails).getFhirContext().getResourceDefinition(nextTarget);
|
||||
if (targetDef != null) {
|
||||
ResourceType code;
|
||||
try {
|
||||
code = ResourceType.fromCode(targetDef.getName());
|
||||
} catch (FHIRException e) {
|
||||
code = null;
|
||||
}
|
||||
// if (code != null) {
|
||||
// param.addTarget(targetDef.getName());
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Read(type = OperationDefinition.class)
|
||||
public OperationDefinition readOperationDefinition(@IdParam IdType theId, RequestDetails theRequestDetails) {
|
||||
if (theId == null || theId.hasIdPart() == false) {
|
||||
|
|
|
@ -476,6 +476,10 @@
|
|||
<action type="fix">
|
||||
Search parameters of type URI did not work in the hapi-fhir-testpage-overlay. This has been corrected.
|
||||
</action>
|
||||
<action type="fix" issue="1568">
|
||||
JPA servers accidentally stripped the type attribute from the server-exported CapabilityStatement
|
||||
when search parameters of type "special" were found. This has been corrected.
|
||||
</action>
|
||||
</release>
|
||||
<release version="4.0.3" date="2019-09-03" description="Igloo (Point Release)">
|
||||
<action type="fix">
|
||||
|
|
Loading…
Reference in New Issue