Merge pull request #1480 from jamesagnew/ks-in-memory-date-compare
%now and in-memory date compare
This commit is contained in:
commit
5020cef56b
|
@ -20,21 +20,20 @@ package ca.uhn.fhir.model.primitive;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import ca.uhn.fhir.model.api.BasePrimitive;
|
||||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.apache.commons.lang3.time.FastDateFormat;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.apache.commons.lang3.time.FastDateFormat;
|
||||
|
||||
import ca.uhn.fhir.model.api.BasePrimitive;
|
||||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
||||
static final long NANOS_PER_MILLIS = 1000000L;
|
||||
|
@ -42,7 +41,8 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
|||
|
||||
private static final FastDateFormat ourHumanDateFormat = FastDateFormat.getDateInstance(FastDateFormat.MEDIUM);
|
||||
private static final FastDateFormat ourHumanDateTimeFormat = FastDateFormat.getDateTimeInstance(FastDateFormat.MEDIUM, FastDateFormat.MEDIUM);
|
||||
|
||||
private static final FastDateFormat ourXmlDateTimeFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
|
||||
public static final String NOW_DATE_CONSTANT = "%now";
|
||||
private String myFractionalSeconds;
|
||||
private TemporalPrecisionEnum myPrecision = null;
|
||||
private TimeZone myTimeZone;
|
||||
|
@ -635,7 +635,12 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
|||
@Override
|
||||
public void setValueAsString(String theValue) throws DataFormatException {
|
||||
clearTimeZone();
|
||||
super.setValueAsString(theValue);
|
||||
|
||||
if (NOW_DATE_CONSTANT.equalsIgnoreCase(theValue)) {
|
||||
super.setValueAsString(ourXmlDateTimeFormat.format(new Date()));
|
||||
} else {
|
||||
super.setValueAsString(theValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -47,7 +47,7 @@ public abstract class BaseParamWithPrefix<T extends BaseParam> extends BaseParam
|
|||
break;
|
||||
} else {
|
||||
char nextChar = theString.charAt(offset);
|
||||
if (nextChar == '-' || Character.isDigit(nextChar)) {
|
||||
if (nextChar == '-' || nextChar == '%' || Character.isDigit(nextChar)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,11 @@ import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
|
|||
import ca.uhn.fhir.jpa.util.TestUtil;
|
||||
import ca.uhn.fhir.parser.StrictErrorHandler;
|
||||
import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.DateTimeType;
|
||||
import org.hl7.fhir.r5.model.Observation;
|
||||
import org.hl7.fhir.r5.model.Patient;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
|
@ -84,6 +88,20 @@ public class ResourceProviderR5Test extends BaseResourceProviderR5Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDateNowSyntax() {
|
||||
Observation observation = new Observation();
|
||||
observation.setEffective(new DateTimeType("1965-08-09"));
|
||||
IIdType oid = myObservationDao.create(observation).getId().toUnqualified();
|
||||
String nowParam = UrlUtil.escapeUrlParam("%now");
|
||||
Bundle output = ourClient
|
||||
.search()
|
||||
.byUrl("Observation?date=lt" + nowParam)
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
List<IIdType> ids = output.getEntry().stream().map(t -> t.getResource().getIdElement().toUnqualified()).collect(Collectors.toList());
|
||||
assertThat(ids, containsInAnyOrder(oid));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
|
|
|
@ -107,6 +107,16 @@
|
|||
<artifactId>logback-classic</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
|
|
@ -23,7 +23,6 @@ package ca.uhn.fhir.jpa.searchparam.matcher;
|
|||
public class InMemoryMatchResult {
|
||||
public static final String PARSE_FAIL = "Failed to translate parse query string";
|
||||
public static final String STANDARD_PARAMETER = "Standard parameters not supported";
|
||||
public static final String PREFIX = "Prefixes not supported";
|
||||
public static final String CHAIN = "Chained references are not supported";
|
||||
public static final String PARAM = "Param not supported";
|
||||
|
||||
|
|
|
@ -29,7 +29,9 @@ import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
|
|||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.param.BaseParamWithPrefix;
|
||||
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
@ -42,7 +44,6 @@ import org.springframework.stereotype.Service;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Service
|
||||
public class InMemoryResourceMatcher {
|
||||
|
@ -57,11 +58,10 @@ public class InMemoryResourceMatcher {
|
|||
/**
|
||||
* This method is called in two different scenarios. With a null theResource, it determines whether database matching might be required.
|
||||
* Otherwise, it tries to perform the match in-memory, returning UNSUPPORTED if it's not possible.
|
||||
*
|
||||
* <p>
|
||||
* Note that there will be cases where it returns UNSUPPORTED with a null resource, but when a non-null resource it returns supported and no match.
|
||||
* This is because an earlier parameter may be matchable in-memory in which case processing stops and we never get to the parameter
|
||||
* that would have required a database call.
|
||||
*
|
||||
*/
|
||||
|
||||
public InMemoryMatchResult match(String theCriteria, IBaseResource theResource, ResourceIndexedSearchParams theSearchParams) {
|
||||
|
@ -86,7 +86,7 @@ public class InMemoryResourceMatcher {
|
|||
String theParamName = entry.getKey();
|
||||
List<List<IQueryParameterType>> theAndOrParams = entry.getValue();
|
||||
InMemoryMatchResult result = matchIdsWithAndOr(theParamName, theAndOrParams, resourceDefinition, theResource, theSearchParams);
|
||||
if (!result.matched()){
|
||||
if (!result.matched()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -102,14 +102,18 @@ public class InMemoryResourceMatcher {
|
|||
if (hasQualifiers(theAndOrParams)) {
|
||||
return InMemoryMatchResult.unsupportedFromParameterAndReason(theParamName, InMemoryMatchResult.STANDARD_PARAMETER);
|
||||
}
|
||||
if (hasPrefixes(theAndOrParams)) {
|
||||
|
||||
return InMemoryMatchResult.unsupportedFromParameterAndReason(theParamName, InMemoryMatchResult.PREFIX);
|
||||
|
||||
}
|
||||
if (hasChain(theAndOrParams)) {
|
||||
return InMemoryMatchResult.unsupportedFromParameterAndReason(theParamName, InMemoryMatchResult.CHAIN);
|
||||
}
|
||||
|
||||
String resourceName = theResourceDefinition.getName();
|
||||
RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(resourceName, theParamName);
|
||||
InMemoryMatchResult checkUnsupportedResult = checkUnsupportedPrefixes(theParamName, paramDef, theAndOrParams);
|
||||
if (!checkUnsupportedResult.supported()) {
|
||||
return checkUnsupportedResult;
|
||||
}
|
||||
|
||||
switch (theParamName) {
|
||||
case IAnyResource.SP_RES_ID:
|
||||
|
||||
|
@ -125,8 +129,7 @@ public class InMemoryResourceMatcher {
|
|||
|
||||
default:
|
||||
|
||||
String resourceName = theResourceDefinition.getName();
|
||||
RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(resourceName, theParamName);
|
||||
|
||||
return matchResourceParam(theParamName, theAndOrParams, theSearchParams, resourceName, paramDef);
|
||||
}
|
||||
}
|
||||
|
@ -137,11 +140,12 @@ public class InMemoryResourceMatcher {
|
|||
}
|
||||
return theAndOrParams.stream().allMatch(nextAnd -> matchIdsOr(nextAnd, theResource));
|
||||
}
|
||||
|
||||
private boolean matchIdsOr(List<IQueryParameterType> theOrParams, IBaseResource theResource) {
|
||||
if (theResource == null) {
|
||||
return true;
|
||||
}
|
||||
return theOrParams.stream().anyMatch(param -> param instanceof StringParam && matchId(((StringParam)param).getValue(), theResource.getIdElement()));
|
||||
return theOrParams.stream().anyMatch(param -> param instanceof StringParam && matchId(((StringParam) param).getValue(), theResource.getIdElement()));
|
||||
}
|
||||
|
||||
private boolean matchId(String theValue, IIdType theId) {
|
||||
|
@ -183,16 +187,48 @@ public class InMemoryResourceMatcher {
|
|||
}
|
||||
|
||||
private boolean hasChain(List<List<IQueryParameterType>> theAndOrParams) {
|
||||
return theAndOrParams.stream().flatMap(List::stream).anyMatch(param -> param instanceof ReferenceParam && ((ReferenceParam)param).getChain() != null);
|
||||
return theAndOrParams.stream().flatMap(List::stream).anyMatch(param -> param instanceof ReferenceParam && ((ReferenceParam) param).getChain() != null);
|
||||
}
|
||||
|
||||
private boolean hasQualifiers(List<List<IQueryParameterType>> theAndOrParams) {
|
||||
return theAndOrParams.stream().flatMap(List::stream).anyMatch(param -> param.getQueryParameterQualifier() != null);
|
||||
}
|
||||
|
||||
private boolean hasPrefixes(List<List<IQueryParameterType>> theAndOrParams) {
|
||||
Predicate<IQueryParameterType> hasPrefixPredicate = param -> param instanceof BaseParamWithPrefix &&
|
||||
((BaseParamWithPrefix) param).getPrefix() != null;
|
||||
return theAndOrParams.stream().flatMap(List::stream).anyMatch(hasPrefixPredicate);
|
||||
private InMemoryMatchResult checkUnsupportedPrefixes(String theParamName, RuntimeSearchParam theParamDef, List<List<IQueryParameterType>> theAndOrParams) {
|
||||
if (theParamDef != null) {
|
||||
for (List<IQueryParameterType> theAndOrParam : theAndOrParams) {
|
||||
for (IQueryParameterType param : theAndOrParam) {
|
||||
if (param instanceof BaseParamWithPrefix) {
|
||||
ParamPrefixEnum prefix = ((BaseParamWithPrefix) param).getPrefix();
|
||||
RestSearchParameterTypeEnum paramType = theParamDef.getParamType();
|
||||
if (!supportedPrefix(prefix, paramType)) {
|
||||
return InMemoryMatchResult.unsupportedFromParameterAndReason(theParamName, String.format("The prefix %s is not supported for param type %s", prefix, paramType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return InMemoryMatchResult.successfulMatch();
|
||||
}
|
||||
|
||||
private boolean supportedPrefix(ParamPrefixEnum theParam, RestSearchParameterTypeEnum theParamType) {
|
||||
if (theParam == null || theParamType == null) {
|
||||
return true;
|
||||
}
|
||||
switch (theParamType) {
|
||||
case DATE:
|
||||
switch (theParam) {
|
||||
case GREATERTHAN:
|
||||
case GREATERTHAN_OR_EQUALS:
|
||||
case LESSTHAN:
|
||||
case LESSTHAN_OR_EQUALS:
|
||||
case EQUAL:
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
package ca.uhn.fhir.jpa.searchparam.matcher;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
|
||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
|
||||
import org.hl7.fhir.r5.model.BaseDateTimeType;
|
||||
import org.hl7.fhir.r5.model.DateTimeType;
|
||||
import org.hl7.fhir.r5.model.Observation;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
public class InMemoryResourceMatcherR5Test {
|
||||
public static final String OBSERVATION_DATE = "1970-10-17";
|
||||
private static final String EARLY_DATE = "1965-08-09";
|
||||
private static final String LATE_DATE = "2000-06-29";
|
||||
|
||||
@Autowired
|
||||
private
|
||||
InMemoryResourceMatcher myInMemoryResourceMatcher;
|
||||
|
||||
@MockBean
|
||||
ISearchParamRegistry mySearchParamRegistry;
|
||||
private Observation myObservation;
|
||||
private ResourceIndexedSearchParams mySearchParams;
|
||||
|
||||
@Configuration
|
||||
public static class SpringConfig {
|
||||
@Bean
|
||||
InMemoryResourceMatcher inMemoryResourceMatcher() {
|
||||
return new InMemoryResourceMatcher();
|
||||
}
|
||||
|
||||
@Bean
|
||||
MatchUrlService matchUrlService() {
|
||||
return new MatchUrlService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
FhirContext fhirContext() {
|
||||
return FhirContext.forR5();
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
RuntimeSearchParam searchParams = new RuntimeSearchParam(null, null, null, null, "Observation.effective", RestSearchParameterTypeEnum.DATE, null, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE);
|
||||
when(mySearchParamRegistry.getSearchParamByName(any(), any())).thenReturn(searchParams);
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "date")).thenReturn(searchParams);
|
||||
myObservation = new Observation();
|
||||
myObservation.setEffective(new DateTimeType(OBSERVATION_DATE));
|
||||
mySearchParams = extractDateSearchParam(myObservation);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDateUnsupportedOps() {
|
||||
testDateUnsupportedOp(ParamPrefixEnum.APPROXIMATE);
|
||||
testDateUnsupportedOp(ParamPrefixEnum.STARTS_AFTER);
|
||||
testDateUnsupportedOp(ParamPrefixEnum.ENDS_BEFORE);
|
||||
testDateUnsupportedOp(ParamPrefixEnum.NOT_EQUAL);
|
||||
}
|
||||
|
||||
private void testDateUnsupportedOp(ParamPrefixEnum theOperator) {
|
||||
InMemoryMatchResult result = myInMemoryResourceMatcher.match("date=" + theOperator.getValue() + OBSERVATION_DATE, myObservation, mySearchParams);
|
||||
assertFalse(result.supported());
|
||||
assertEquals("Parameter: <date> Reason: The prefix " + theOperator + " is not supported for param type DATE", result.getUnsupportedReason());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDateSupportedOps() {
|
||||
testDateSupportedOp(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, true, true, false);
|
||||
testDateSupportedOp(ParamPrefixEnum.GREATERTHAN, true, false, false);
|
||||
testDateSupportedOp(ParamPrefixEnum.EQUAL, false, true, false);
|
||||
testDateSupportedOp(ParamPrefixEnum.LESSTHAN_OR_EQUALS, false, true, true);
|
||||
testDateSupportedOp(ParamPrefixEnum.LESSTHAN, false, false, true);
|
||||
}
|
||||
|
||||
private void testDateSupportedOp(ParamPrefixEnum theOperator, boolean theEarly, boolean theSame, boolean theLater) {
|
||||
String equation = "date=" + theOperator.getValue();
|
||||
{
|
||||
InMemoryMatchResult result = myInMemoryResourceMatcher.match(equation + EARLY_DATE, myObservation, mySearchParams);
|
||||
assertTrue(result.getUnsupportedReason(), result.supported());
|
||||
assertEquals(result.matched(), theEarly);
|
||||
}
|
||||
{
|
||||
InMemoryMatchResult result = myInMemoryResourceMatcher.match(equation + OBSERVATION_DATE, myObservation, mySearchParams);
|
||||
assertTrue(result.getUnsupportedReason(), result.supported());
|
||||
assertEquals(result.matched(), theSame);
|
||||
}
|
||||
{
|
||||
InMemoryMatchResult result = myInMemoryResourceMatcher.match(equation + LATE_DATE, myObservation, mySearchParams);
|
||||
assertTrue(result.getUnsupportedReason(), result.supported());
|
||||
assertEquals(result.matched(), theLater);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNowPast() {
|
||||
InMemoryMatchResult result = myInMemoryResourceMatcher.match("date=lt" + BaseDateTimeDt.NOW_DATE_CONSTANT, myObservation, mySearchParams);
|
||||
assertTrue(result.getUnsupportedReason(), result.supported());
|
||||
assertTrue(result.matched());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNowNextWeek() {
|
||||
Observation futureObservation = new Observation();
|
||||
Instant nextWeek = Instant.now().plus(Duration.ofDays(7));
|
||||
futureObservation.setEffective(new DateTimeType(Date.from(nextWeek)));
|
||||
ResourceIndexedSearchParams searchParams = extractDateSearchParam(futureObservation);
|
||||
|
||||
InMemoryMatchResult result = myInMemoryResourceMatcher.match("date=gt" + BaseDateTimeDt.NOW_DATE_CONSTANT, futureObservation, searchParams);
|
||||
assertTrue(result.getUnsupportedReason(), result.supported());
|
||||
assertTrue(result.matched());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNowNextMinute() {
|
||||
Observation futureObservation = new Observation();
|
||||
Instant nextMinute = Instant.now().plus(Duration.ofMinutes(1));
|
||||
futureObservation.setEffective(new DateTimeType(Date.from(nextMinute)));
|
||||
ResourceIndexedSearchParams searchParams = extractDateSearchParam(futureObservation);
|
||||
|
||||
InMemoryMatchResult result = myInMemoryResourceMatcher.match("date=gt" + BaseDateTimeDt.NOW_DATE_CONSTANT, futureObservation, searchParams);
|
||||
assertTrue(result.getUnsupportedReason(), result.supported());
|
||||
assertTrue(result.matched());
|
||||
}
|
||||
|
||||
private ResourceIndexedSearchParams extractDateSearchParam(Observation theObservation) {
|
||||
ResourceIndexedSearchParams retval = new ResourceIndexedSearchParams();
|
||||
BaseDateTimeType dateValue = (BaseDateTimeType) theObservation.getEffective();
|
||||
ResourceIndexedSearchParamDate dateParam = new ResourceIndexedSearchParamDate("date", dateValue.getValue(), dateValue.getValue(), dateValue.getValueAsString());
|
||||
retval.myDateParams.add(dateParam);
|
||||
return retval;
|
||||
}
|
||||
|
||||
}
|
|
@ -549,7 +549,7 @@ public class InMemorySubscriptionMatcherR3Test extends BaseSubscriptionDstu3Test
|
|||
CommunicationRequest cr = new CommunicationRequest();
|
||||
cr.getRequester().getAgent().setReference("Organization/O1276");
|
||||
cr.setOccurrence(new DateTimeType("2019-02-08T00:01:00-05:00"));
|
||||
assertUnsupported(cr, criteria);
|
||||
assertMatched(cr, criteria);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import ca.uhn.fhir.rest.api.Constants;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.validation.IValidationContext;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
package org.hl7.fhir.instance.hapi.validation;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.validation.IValidationContext;
|
||||
|
@ -14,11 +8,7 @@ import ca.uhn.fhir.validation.IValidatorModule;
|
|||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.*;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
|
@ -27,16 +17,10 @@ import org.fhir.ucum.UcumService;
|
|||
import org.hl7.fhir.convertors.NullVersionConverterAdvisor50;
|
||||
import org.hl7.fhir.convertors.VersionConvertorAdvisor50;
|
||||
import org.hl7.fhir.convertors.VersionConvertor_10_50;
|
||||
import org.hl7.fhir.convertors.VersionConvertor_10_50;
|
||||
import org.hl7.fhir.dstu2.model.*;
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.TerminologyServiceException;
|
||||
import org.hl7.fhir.dstu2.model.CodeableConcept;
|
||||
import org.hl7.fhir.dstu2.model.Coding;
|
||||
import org.hl7.fhir.dstu2.model.Questionnaire;
|
||||
import org.hl7.fhir.dstu2.model.Resource;
|
||||
import org.hl7.fhir.dstu2.model.StructureDefinition;
|
||||
import org.hl7.fhir.dstu2.model.ValueSet;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.formats.IParser;
|
||||
import org.hl7.fhir.r5.formats.ParserType;
|
||||
|
@ -58,20 +42,17 @@ import org.w3c.dom.Element;
|
|||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
public class FhirInstanceValidator extends BaseValidatorBridge implements IValidatorModule {
|
||||
|
||||
|
|
|
@ -30,9 +30,6 @@ import org.hl7.fhir.utilities.TerminologyServiceOptions;
|
|||
import org.hl7.fhir.utilities.TranslationServices;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -562,7 +562,7 @@
|
|||
|
||||
<properties>
|
||||
|
||||
<fhir_core_version>4.0.8-SNAPSHOT</fhir_core_version>
|
||||
<fhir_core_version>4.0.10-SNAPSHOT</fhir_core_version>
|
||||
<ucum_version>1.0.2</ucum_version>
|
||||
|
||||
<!-- configure timestamp in MANIFEST.MF for maven-war-provider -->
|
||||
|
|
|
@ -121,6 +121,13 @@
|
|||
The GraphQL provider did not wrap the respone in a "data" element as described in the FHIR
|
||||
specification. This has been corrected.
|
||||
</action>
|
||||
<action type="add">
|
||||
Added support for comparing resource dates to the current time via a new variable %now. E.g.
|
||||
Procedure?date=gt%now would match future procedures.
|
||||
</action>
|
||||
<action type="add">
|
||||
Add support for in-memory matching on date comparisons ge,gt,eq,lt,le.
|
||||
</action>
|
||||
<action type="fix">
|
||||
When using the Consent Service and denying a resource via the "Will See Resource" method, the resource ID
|
||||
and version were still returned to the user. This has been corrected so that no details about
|
||||
|
|
Loading…
Reference in New Issue