Merge branch 'master' of github.com:hapifhir/hapi-fhir
This commit is contained in:
commit
2e6fb10df3
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.util;
|
package ca.uhn.fhir.util;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Core Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* 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 com.google.common.collect.ArrayListMultimap;
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.ListMultimap;
|
import com.google.common.collect.ListMultimap;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-cli</artifactId>
|
<artifactId>hapi-fhir-cli</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../../hapi-deployable-pom</relativePath>
|
<relativePath>../../hapi-deployable-pom</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 3145
|
||||||
|
title: "RequestValidatingInteceptor incorrectly prevented GraphQL requests from being submitted using
|
||||||
|
the HTTP POST form of the GraphQL operation."
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 3153
|
||||||
|
title: "Updated UnknownCodeSystemWarningValidationSupport to allow the throwing of warnings if
|
||||||
|
configured to do so."
|
|
@ -11,7 +11,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -156,6 +156,14 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
|
<artifactId>hapi-fhir-storage</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>tests</classifier>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.jpa.dao.search;
|
package ca.uhn.fhir.jpa.dao.search;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* 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 ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.jpa.dao.search;
|
package ca.uhn.fhir.jpa.dao.search;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* 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 ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||||
|
@ -26,7 +46,6 @@ public class ExtendedLuceneIndexExtractor {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public ExtendedLuceneIndexData extract(ResourceIndexedSearchParams theNewParams) {
|
public ExtendedLuceneIndexData extract(ResourceIndexedSearchParams theNewParams) {
|
||||||
// wip mb this is testable now.
|
|
||||||
ExtendedLuceneIndexData retVal = new ExtendedLuceneIndexData(myContext);
|
ExtendedLuceneIndexData retVal = new ExtendedLuceneIndexData(myContext);
|
||||||
|
|
||||||
theNewParams.myStringParams.forEach(nextParam ->
|
theNewParams.myStringParams.forEach(nextParam ->
|
||||||
|
@ -39,7 +58,7 @@ public class ExtendedLuceneIndexExtractor {
|
||||||
|
|
||||||
// awkwardly, links are shared between different search params if they use the same path,
|
// awkwardly, links are shared between different search params if they use the same path,
|
||||||
// so we re-build the linkage.
|
// so we re-build the linkage.
|
||||||
// WIP MB is this the right design? Or should we follow JPA and share these?
|
// WIPMB is this the right design? Or should we follow JPA and share these?
|
||||||
Map<String, List<String>> linkPathToParamName = new HashMap<>();
|
Map<String, List<String>> linkPathToParamName = new HashMap<>();
|
||||||
for (String nextParamName : theNewParams.getPopulatedResourceLinkParameters()) {
|
for (String nextParamName : theNewParams.getPopulatedResourceLinkParameters()) {
|
||||||
RuntimeSearchParam sp = myParams.get(nextParamName);
|
RuntimeSearchParam sp = myParams.get(nextParamName);
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.jpa.dao.search;
|
package ca.uhn.fhir.jpa.dao.search;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* 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 ca.uhn.fhir.context.RuntimeSearchParam;
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
|
|
|
@ -19,3 +19,23 @@
|
||||||
* Activated by {@link ca.uhn.fhir.jpa.api.config.DaoConfig#setAdvancedLuceneIndexing(boolean)}.
|
* Activated by {@link ca.uhn.fhir.jpa.api.config.DaoConfig#setAdvancedLuceneIndexing(boolean)}.
|
||||||
*/
|
*/
|
||||||
package ca.uhn.fhir.jpa.dao.search;
|
package ca.uhn.fhir.jpa.dao.search;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* 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%
|
||||||
|
*/
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
package ca.uhn.fhir.jpa.dao;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
|
||||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
|
||||||
import ca.uhn.fhir.jpa.conformance.DateSearchTestCase;
|
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
|
||||||
import ca.uhn.fhir.rest.param.DateParam;
|
|
||||||
import ca.uhn.fhir.util.FhirTerser;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.hl7.fhir.r4.model.Observation;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.transaction.support.TransactionCallback;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run the tests defined in {@link DateSearchTestCase} in a DAO test as a @Nested suite.
|
|
||||||
*/
|
|
||||||
public abstract class BaseDAODateSearchTest {
|
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(BaseDAODateSearchTest.class);
|
|
||||||
|
|
||||||
/** Id of test Observation */
|
|
||||||
IIdType myObservationId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for our date search operators.
|
|
||||||
* <p>
|
|
||||||
* Be careful - date searching is defined by set relations over intervals, not a simple number comparison.
|
|
||||||
* See http://hl7.org/fhir/search.html#prefix for details.
|
|
||||||
* <p>
|
|
||||||
*
|
|
||||||
* @param theResourceDate the date to use as Observation effective date
|
|
||||||
* @param theQuery the query parameter value including prefix (e.g. eq2020-01-01)
|
|
||||||
* @param theExpectedMatch true if tdheQuery should match theResourceDate.
|
|
||||||
*/
|
|
||||||
@ParameterizedTest
|
|
||||||
// use @CsvSource to debug individual cases.
|
|
||||||
//@CsvSource("2019-12-31T08:00:00,eq2020,false,inline,1")
|
|
||||||
@MethodSource("dateSearchCases")
|
|
||||||
public void testDateSearchMatching(String theResourceDate, String theQuery, Boolean theExpectedMatch, String theFileName, int theLineNumber) {
|
|
||||||
if (isShouldSkip(theResourceDate, theQuery)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// setup
|
|
||||||
createObservationWithEffectiveDate(theResourceDate);
|
|
||||||
|
|
||||||
// run the query
|
|
||||||
boolean matched = isSearchMatch(theQuery);
|
|
||||||
|
|
||||||
String message =
|
|
||||||
"Expected " + theQuery + " to " +
|
|
||||||
(theExpectedMatch ? "" : "not ") + "match " + theResourceDate +
|
|
||||||
" (" + theFileName + ":" + theLineNumber + ")"; // wrap this in () so tools recognize the line reference.
|
|
||||||
assertEquals(theExpectedMatch, matched, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isShouldSkip(String theResourceDate, String theQuery) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need these from the test container
|
|
||||||
abstract protected FhirContext getMyFhirCtx();
|
|
||||||
abstract protected <T> T doInTransaction(TransactionCallback<T> daoMethodOutcomeTransactionCallback);
|
|
||||||
abstract protected <T extends IBaseResource> IFhirResourceDao<T> getObservationDao();
|
|
||||||
|
|
||||||
protected void createObservationWithEffectiveDate(String theResourceDate) {
|
|
||||||
IBaseResource obs = getMyFhirCtx().getResourceDefinition("Observation").newInstance();
|
|
||||||
FhirTerser fhirTerser = getMyFhirCtx().newTerser();
|
|
||||||
fhirTerser.addElement(obs, "effectiveDateTime", theResourceDate);
|
|
||||||
ourLog.info("obs {}", getMyFhirCtx().newJsonParser().encodeResourceToString(obs));
|
|
||||||
|
|
||||||
DaoMethodOutcome createOutcome = doInTransaction(s -> getObservationDao().create(obs));
|
|
||||||
myObservationId = createOutcome.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the query string match the observation created during setup?
|
|
||||||
*/
|
|
||||||
protected boolean isSearchMatch(String theQuery) {
|
|
||||||
SearchParameterMap map = SearchParameterMap.newSynchronous();
|
|
||||||
map.add(Observation.SP_DATE, new DateParam(theQuery));
|
|
||||||
ourLog.info("Searching for observation {}", map);
|
|
||||||
|
|
||||||
IBundleProvider results = getObservationDao().search(map);
|
|
||||||
|
|
||||||
boolean matched = results.getAllResourceIds().contains(myObservationId.getIdPart());
|
|
||||||
return matched;
|
|
||||||
}
|
|
||||||
|
|
||||||
static List<Arguments> dateSearchCases() {
|
|
||||||
return DateSearchTestCase.ourCases.stream()
|
|
||||||
.map(DateSearchTestCase::toArguments)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,13 +1,11 @@
|
||||||
package ca.uhn.fhir.jpa.dao.r4;
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||||
import ca.uhn.fhir.interceptor.api.IAnonymousInterceptor;
|
import ca.uhn.fhir.interceptor.api.IAnonymousInterceptor;
|
||||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
import ca.uhn.fhir.jpa.dao.BaseDateSearchDaoTests;
|
||||||
import ca.uhn.fhir.jpa.dao.BaseDAODateSearchTest;
|
|
||||||
import ca.uhn.fhir.jpa.entity.Search;
|
import ca.uhn.fhir.jpa.entity.Search;
|
||||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||||
|
@ -5316,8 +5314,7 @@ public class FhirResourceDaoR4LegacySearchBuilderTest extends BaseJpaR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
public class DateSearchTests extends BaseDAODateSearchTest {
|
public class DateSearchTests extends BaseDateSearchDaoTests {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* legacy builder didn't get the year/month date search fixes, so skip anything wider than a day.
|
* legacy builder didn't get the year/month date search fixes, so skip anything wider than a day.
|
||||||
*/
|
*/
|
||||||
|
@ -5328,16 +5325,8 @@ public class FhirResourceDaoR4LegacySearchBuilderTest extends BaseJpaR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FhirContext getMyFhirCtx() {
|
protected Fixture getFixture() {
|
||||||
return myFhirCtx;
|
return new TestDataBuilderFixture(FhirResourceDaoR4LegacySearchBuilderTest.this, myObservationDao);
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected <T> T doInTransaction(TransactionCallback<T> theCallback) {
|
|
||||||
return new TransactionTemplate(myTxManager).execute(theCallback);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected IFhirResourceDao<Observation> getObservationDao() {
|
|
||||||
return myObservationDao;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package ca.uhn.fhir.jpa.dao.r4;
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.config.TestR4WithLuceneDisabledConfig;
|
import ca.uhn.fhir.jpa.config.TestR4WithLuceneDisabledConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.BaseDAODateSearchTest;
|
import ca.uhn.fhir.jpa.dao.BaseDateSearchDaoTests;
|
||||||
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
|
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
|
||||||
|
import ca.uhn.fhir.jpa.dao.DaoTestDataBuilder;
|
||||||
|
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||||
import org.hl7.fhir.r4.model.Observation;
|
import org.hl7.fhir.r4.model.Observation;
|
||||||
import org.junit.jupiter.api.Nested;
|
import org.junit.jupiter.api.Nested;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
@ -16,8 +19,6 @@ import org.springframework.test.annotation.DirtiesContext;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.support.TransactionCallback;
|
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
@ -33,6 +34,8 @@ public class FhirResourceDaoR4LuceneDisabledStandardQueries extends BaseJpaTest
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("myObservationDaoR4")
|
@Qualifier("myObservationDaoR4")
|
||||||
IFhirResourceDao<Observation> myObservationDao;
|
IFhirResourceDao<Observation> myObservationDao;
|
||||||
|
@Autowired
|
||||||
|
protected DaoRegistry myDaoRegistry;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PlatformTransactionManager getTxManager() {
|
protected PlatformTransactionManager getTxManager() {
|
||||||
|
@ -45,22 +48,11 @@ public class FhirResourceDaoR4LuceneDisabledStandardQueries extends BaseJpaTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
public class DateSearchTests extends BaseDAODateSearchTest {
|
public class DateSearchTests extends BaseDateSearchDaoTests {
|
||||||
@Override
|
@Override
|
||||||
protected FhirContext getMyFhirCtx() {
|
protected Fixture getFixture() {
|
||||||
return myFhirCtx;
|
DaoTestDataBuilder testDataBuilder = new DaoTestDataBuilder(myFhirCtx, myDaoRegistry, new SystemRequestDetails());
|
||||||
}
|
return new TestDataBuilderFixture<>(testDataBuilder, myObservationDao);
|
||||||
|
|
||||||
@Override
|
|
||||||
protected <T> T doInTransaction(TransactionCallback<T> theCallback) {
|
|
||||||
return new TransactionTemplate(myTxManager).execute(
|
|
||||||
theCallback
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected IFhirResourceDao<Observation> getObservationDao() {
|
|
||||||
return myObservationDao;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||||
myValidationSettings.setLocalReferenceValidationDefaultPolicy(IResourceValidator.ReferenceValidationPolicy.IGNORE);
|
myValidationSettings.setLocalReferenceValidationDefaultPolicy(IResourceValidator.ReferenceValidationPolicy.IGNORE);
|
||||||
myFhirCtx.setParserErrorHandler(new StrictErrorHandler());
|
myFhirCtx.setParserErrorHandler(new StrictErrorHandler());
|
||||||
|
|
||||||
myUnknownCodeSystemWarningValidationSupport.setAllowNonExistentCodeSystem(UnknownCodeSystemWarningValidationSupport.ALLOW_NON_EXISTENT_CODE_SYSTEM_DEFAULT);
|
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(UnknownCodeSystemWarningValidationSupport.DEFAULT_SEVERITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -162,11 +162,12 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* By default an unknown code system should fail vaildation
|
* By default, an unknown code system should fail validation
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeInValueSetWithUnknownCodeSystem_Warning() {
|
public void testValidateCodeInValueSetWithUnknownCodeSystem_Warning() {
|
||||||
myUnknownCodeSystemWarningValidationSupport.setAllowNonExistentCodeSystem(true);
|
// set to warning
|
||||||
|
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(IValidationSupport.IssueSeverity.WARNING);
|
||||||
|
|
||||||
createStructureDefWithBindingToUnknownCs();
|
createStructureDefWithBindingToUnknownCs();
|
||||||
|
|
||||||
|
@ -189,14 +190,14 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||||
oo = validateAndReturnOutcome(obs);
|
oo = validateAndReturnOutcome(obs);
|
||||||
encoded = encode(oo);
|
encoded = encode(oo);
|
||||||
ourLog.info(encoded);
|
ourLog.info(encoded);
|
||||||
assertEquals("No issues detected during validation", oo.getIssueFirstRep().getDiagnostics(), encoded);
|
assertTrue(oo.getIssueFirstRep().getDiagnostics().contains("No issues detected during validation"));
|
||||||
|
|
||||||
// Invalid code
|
// Invalid code
|
||||||
obs.setValue(new Quantity().setSystem("http://cs").setCode("code99").setValue(123));
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code99").setValue(123));
|
||||||
oo = validateAndReturnOutcome(obs);
|
oo = validateAndReturnOutcome(obs);
|
||||||
encoded = encode(oo);
|
encoded = encode(oo);
|
||||||
ourLog.info(encoded);
|
ourLog.info(encoded);
|
||||||
assertEquals("No issues detected during validation", oo.getIssueFirstRep().getDiagnostics(), encoded);
|
assertTrue(oo.getIssueFirstRep().getDiagnostics().contains("No issues detected during validation"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.jpa.model.search;
|
package ca.uhn.fhir.jpa.model.search;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Model
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* 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 ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.jpa.model.search;
|
package ca.uhn.fhir.jpa.model.search;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Model
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* 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 org.hibernate.search.engine.backend.document.DocumentElement;
|
import org.hibernate.search.engine.backend.document.DocumentElement;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.jpa.model.search;
|
package ca.uhn.fhir.jpa.model.search;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Model
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* 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 ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
import org.hibernate.search.engine.backend.document.DocumentElement;
|
import org.hibernate.search.engine.backend.document.DocumentElement;
|
||||||
|
|
|
@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.model.search;
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR JPA Server
|
* HAPI FHIR JPA Model
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||||
* %%
|
* %%
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -306,10 +306,17 @@ public abstract class BaseValidatingInterceptor<T> extends ValidationResultEnric
|
||||||
* Note: May return null
|
* Note: May return null
|
||||||
*/
|
*/
|
||||||
protected ValidationResult validate(T theRequest, RequestDetails theRequestDetails) {
|
protected ValidationResult validate(T theRequest, RequestDetails theRequestDetails) {
|
||||||
if (theRequest == null) {
|
if (theRequest == null || theRequestDetails == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (theRequestDetails.getRestOperationType()) {
|
||||||
|
case GRAPHQL_REQUEST:
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
FhirValidator validator;
|
FhirValidator validator;
|
||||||
if (myValidator != null) {
|
if (myValidator != null) {
|
||||||
validator = myValidator;
|
validator = myValidator;
|
||||||
|
|
|
@ -34,6 +34,7 @@ import ca.uhn.fhir.rest.api.server.ResponseDetails;
|
||||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
@ -109,8 +110,10 @@ public class GraphQLMethodBinding extends OperationMethodBinding {
|
||||||
private String getQueryValue(Object[] methodParams) {
|
private String getQueryValue(Object[] methodParams) {
|
||||||
switch (myMethodRequestType) {
|
switch (myMethodRequestType) {
|
||||||
case POST:
|
case POST:
|
||||||
|
Validate.notNull(myQueryBodyParamIndex, "GraphQL method does not have @" + GraphQLQueryBody.class.getSimpleName() + " parameter");
|
||||||
return (String) methodParams[myQueryBodyParamIndex];
|
return (String) methodParams[myQueryBodyParamIndex];
|
||||||
case GET:
|
case GET:
|
||||||
|
Validate.notNull(myQueryUrlParamIndex, "GraphQL method does not have @" + GraphQLQueryUrl.class.getSimpleName() + " parameter");
|
||||||
return (String) methodParams[myQueryUrlParamIndex];
|
return (String) methodParams[myQueryUrlParamIndex];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -44,6 +44,8 @@ import java.util.Collection;
|
||||||
import static ca.uhn.fhir.rest.api.Constants.CT_GRAPHQL;
|
import static ca.uhn.fhir.rest.api.Constants.CT_GRAPHQL;
|
||||||
import static ca.uhn.fhir.rest.api.Constants.CT_JSON;
|
import static ca.uhn.fhir.rest.api.Constants.CT_JSON;
|
||||||
import static ca.uhn.fhir.rest.server.method.ResourceParameter.createRequestReader;
|
import static ca.uhn.fhir.rest.server.method.ResourceParameter.createRequestReader;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.trim;
|
||||||
|
|
||||||
public class GraphQLQueryBodyParameter implements IParameter {
|
public class GraphQLQueryBodyParameter implements IParameter {
|
||||||
|
|
||||||
|
@ -51,9 +53,16 @@ public class GraphQLQueryBodyParameter implements IParameter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
String ctValue = theRequest.getHeader(Constants.HEADER_CONTENT_TYPE);
|
String ctValue = defaultString(theRequest.getHeader(Constants.HEADER_CONTENT_TYPE));
|
||||||
Reader requestReader = createRequestReader(theRequest);
|
Reader requestReader = createRequestReader(theRequest);
|
||||||
|
|
||||||
|
// Trim off "; charset=FOO" from the content-type header
|
||||||
|
int semicolonIdx = ctValue.indexOf(';');
|
||||||
|
if (semicolonIdx != -1) {
|
||||||
|
ctValue = ctValue.substring(0, semicolonIdx);
|
||||||
|
}
|
||||||
|
ctValue = trim(ctValue);
|
||||||
|
|
||||||
if (CT_JSON.equals(ctValue)) {
|
if (CT_JSON.equals(ctValue)) {
|
||||||
try {
|
try {
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId>
|
<artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>
|
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -75,6 +75,13 @@
|
||||||
<artifactId>hapi-fhir-jpaserver-searchparam</artifactId>
|
<artifactId>hapi-fhir-jpaserver-searchparam</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
|
<artifactId>hapi-fhir-test-utilities</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate.search</groupId>
|
<groupId>org.hibernate.search</groupId>
|
||||||
<artifactId>hibernate-search-mapper-orm</artifactId>
|
<artifactId>hibernate-search-mapper-orm</artifactId>
|
||||||
|
@ -151,6 +158,18 @@
|
||||||
</plugins>
|
</plugins>
|
||||||
</pluginManagement>
|
</pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.2.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>test-jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.jacoco</groupId>
|
<groupId>org.jacoco</groupId>
|
||||||
<artifactId>jacoco-maven-plugin</artifactId>
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||||
|
import ca.uhn.fhir.jpa.conformance.DateSearchTestCase;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
import ca.uhn.fhir.rest.param.DateParam;
|
||||||
|
import ca.uhn.fhir.test.utilities.ITestDataBuilder;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the tests defined in {@link DateSearchTestCase} in a DAO test as a @Nested suite.
|
||||||
|
*/
|
||||||
|
public abstract class BaseDateSearchDaoTests {
|
||||||
|
private static final Logger ourLog = LoggerFactory.getLogger(BaseDateSearchDaoTests.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id of test Observation
|
||||||
|
*/
|
||||||
|
IIdType myObservationId;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for our date search operators.
|
||||||
|
* <p>
|
||||||
|
* Be careful - date searching is defined by set relations over intervals, not a simple number comparison.
|
||||||
|
* See http://hl7.org/fhir/search.html#prefix for details.
|
||||||
|
* <p>
|
||||||
|
* To debug, uncomment the @CsvSource line and comment @MethodSource to run a single case
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param theResourceDate the date to use as Observation effective date
|
||||||
|
* @param theQuery the query parameter value including prefix (e.g. eq2020-01-01)
|
||||||
|
* @param theExpectedMatch true if theQuery should match theResourceDate.
|
||||||
|
* @param theFileName source file for test case
|
||||||
|
* @param theLineNumber source file line number for test case (-1 for inline tests)
|
||||||
|
*/
|
||||||
|
@ParameterizedTest
|
||||||
|
// use @CsvSource to debug individual cases.
|
||||||
|
//@CsvSource("2019-12-31T08:00:00,eq2020,false,inline,1")
|
||||||
|
@MethodSource("dateSearchCases")
|
||||||
|
public void testDateSearchMatching(String theResourceDate, String theQuery, boolean theExpectedMatch, String theFileName, int theLineNumber) {
|
||||||
|
Fixture fixture = getFixture();
|
||||||
|
if (isShouldSkip(theResourceDate, theQuery)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup
|
||||||
|
myObservationId = fixture.createObservationWithEffectiveDate(theResourceDate);
|
||||||
|
|
||||||
|
// run the query
|
||||||
|
boolean matched = fixture.isObservationSearchMatch(theQuery, myObservationId);
|
||||||
|
|
||||||
|
assertExpectedMatch(theResourceDate, theQuery, theExpectedMatch, matched, theFileName, theLineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected boolean isShouldSkip(String theResourceDate, String theQuery) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void assertExpectedMatch(String theResourceDate, String theQuery, boolean theExpectedMatch, boolean matched, String theFileName, int theLineNumber) {
|
||||||
|
String message =
|
||||||
|
"Expected " + theQuery + " to " +
|
||||||
|
(theExpectedMatch ? "" : "not ") + "match " + theResourceDate +
|
||||||
|
" (" + theFileName + ":" + theLineNumber + ")"; // wrap this in () so tools recognize the line reference.
|
||||||
|
assertEquals(theExpectedMatch, matched, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn the cases into expanded arguments for better reporting output and debugging
|
||||||
|
*/
|
||||||
|
public static List<Arguments> dateSearchCases() {
|
||||||
|
return DateSearchTestCase.ourCases.stream()
|
||||||
|
.map(DateSearchTestCase::toArguments)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to provide local setup and query services.
|
||||||
|
*
|
||||||
|
* Use an abstract method instead of a constructor because JUnit has a such a funky lifecycle.
|
||||||
|
*/
|
||||||
|
protected abstract Fixture getFixture();
|
||||||
|
|
||||||
|
public interface Fixture {
|
||||||
|
/**
|
||||||
|
* Create an observation and save it
|
||||||
|
*/
|
||||||
|
IIdType createObservationWithEffectiveDate(String theResourceDate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does date=theQuery match theObservationId created
|
||||||
|
*/
|
||||||
|
boolean isObservationSearchMatch(String theQuery, IIdType theObservationId);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TestDataBuilderFixture<O extends IBaseResource> implements Fixture {
|
||||||
|
final ITestDataBuilder myTestDataBuilder;
|
||||||
|
final IFhirResourceDao<O> myObservationDao;
|
||||||
|
|
||||||
|
public TestDataBuilderFixture(ITestDataBuilder theTestDataBuilder, IFhirResourceDao<O> theObservationDao) {
|
||||||
|
myTestDataBuilder = theTestDataBuilder;
|
||||||
|
myObservationDao = theObservationDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType createObservationWithEffectiveDate(String theResourceDate) {
|
||||||
|
return myTestDataBuilder.createObservation(myTestDataBuilder.withEffectiveDate(theResourceDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isObservationSearchMatch(String theQuery, IIdType theObservationId) {
|
||||||
|
SearchParameterMap map = SearchParameterMap.newSynchronous();
|
||||||
|
map.add("date", new DateParam(theQuery));
|
||||||
|
ourLog.info("Searching for observation {}", map);
|
||||||
|
|
||||||
|
IBundleProvider results = myObservationDao.search(map);
|
||||||
|
|
||||||
|
boolean matched = results.getAllResourceIds().contains(theObservationId.getIdPart());
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||||
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||||
|
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||||
|
import ca.uhn.fhir.test.utilities.ITestDataBuilder;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
|
||||||
|
public class DaoTestDataBuilder implements ITestDataBuilder {
|
||||||
|
final FhirContext myFhirCtx;
|
||||||
|
final DaoRegistry myDaoRegistry;
|
||||||
|
SystemRequestDetails mySrd;
|
||||||
|
|
||||||
|
public DaoTestDataBuilder(FhirContext theFhirCtx, DaoRegistry theDaoRegistry, SystemRequestDetails theSrd) {
|
||||||
|
myFhirCtx = theFhirCtx;
|
||||||
|
myDaoRegistry = theDaoRegistry;
|
||||||
|
mySrd = theSrd;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType doCreateResource(IBaseResource theResource) {
|
||||||
|
//noinspection rawtypes
|
||||||
|
IFhirResourceDao dao = myDaoRegistry.getResourceDao(theResource.getClass());
|
||||||
|
//noinspection unchecked
|
||||||
|
return dao.create(theResource, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IIdType doUpdateResource(IBaseResource theResource) {
|
||||||
|
//noinspection rawtypes
|
||||||
|
IFhirResourceDao dao = myDaoRegistry.getResourceDao(theResource.getClass());
|
||||||
|
//noinspection unchecked
|
||||||
|
return dao.update(theResource, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FhirContext getFhirContext() {
|
||||||
|
return myFhirCtx;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ import java.io.InputStreamReader;
|
||||||
import java.io.LineNumberReader;
|
import java.io.LineNumberReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -68,17 +69,23 @@ public class DateSearchTestCase {
|
||||||
*/
|
*/
|
||||||
public final static List<DateSearchTestCase> ourCases;
|
public final static List<DateSearchTestCase> ourCases;
|
||||||
static {
|
static {
|
||||||
|
ourCases = new ArrayList<>();
|
||||||
|
ourCases.addAll(expandedCases());
|
||||||
|
ourCases.addAll(compactCases());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<DateSearchTestCase> expandedCases() {
|
||||||
String csv = "DateSearchTestCase.csv";
|
String csv = "DateSearchTestCase.csv";
|
||||||
InputStream resource = DateSearchTestCase.class.getResourceAsStream(csv);
|
InputStream resource = DateSearchTestCase.class.getResourceAsStream(csv);
|
||||||
assert resource != null;
|
assert resource != null;
|
||||||
InputStreamReader inputStreamReader = new InputStreamReader(resource, StandardCharsets.UTF_8);
|
InputStreamReader inputStreamReader = new InputStreamReader(resource, StandardCharsets.UTF_8);
|
||||||
ourCases = parseCsvCases(inputStreamReader, csv);
|
List<DateSearchTestCase> cases = parseCsvCases(inputStreamReader, csv);
|
||||||
try {
|
try {
|
||||||
resource.close();
|
resource.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
ourCases.addAll(compactCases());
|
return cases;
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<DateSearchTestCase> parseCsvCases(Reader theSource, String theFileName) {
|
static List<DateSearchTestCase> parseCsvCases(Reader theSource, String theFileName) {
|
||||||
|
@ -122,7 +129,7 @@ public class DateSearchTestCase {
|
||||||
String resourceValue = fields[0].trim();
|
String resourceValue = fields[0].trim();
|
||||||
String truePrefixes = fields[1].trim();
|
String truePrefixes = fields[1].trim();
|
||||||
String queryValue = fields[2].trim();
|
String queryValue = fields[2].trim();
|
||||||
Set<String> expectedTruePrefixes = Arrays.stream(truePrefixes.split(" +")).map(String::trim).collect(Collectors.toSet());
|
Set<String> expectedTruePrefixes = Arrays.stream(truePrefixes.split("\\s+")).map(String::trim).collect(Collectors.toSet());
|
||||||
|
|
||||||
// expand to one test case per supportedPrefixes
|
// expand to one test case per supportedPrefixes
|
||||||
return supportedPrefixes.stream()
|
return supportedPrefixes.stream()
|
||||||
|
|
|
@ -86,6 +86,13 @@ public interface ITestDataBuilder {
|
||||||
return t -> __setPrimitiveChild(getFhirContext(), t, "status", "code", theStatus);
|
return t -> __setPrimitiveChild(getFhirContext(), t, "status", "code", theStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Observation.effectiveDate
|
||||||
|
*/
|
||||||
|
default Consumer<IBaseResource> withEffectiveDate(String theDate) {
|
||||||
|
return t -> __setPrimitiveChild(getFhirContext(), t, "effectiveDateTime", "dateTime", theDate);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set [Resource].identifier.system and [Resource].identifier.value
|
* Set [Resource].identifier.system and [Resource].identifier.value
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,19 +20,22 @@ package ca.uhn.fhir.test.utilities.server;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
|
||||||
public class ResourceProviderExtension implements BeforeEachCallback, AfterEachCallback {
|
public class ResourceProviderExtension<T> implements BeforeEachCallback, AfterEachCallback {
|
||||||
|
|
||||||
private final RestfulServerExtension myRestfulServerExtension;
|
private final RestfulServerExtension myRestfulServerExtension;
|
||||||
private Object myProvider;
|
private final T myProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
public ResourceProviderExtension(RestfulServerExtension theRestfulServerExtension, Object theProvider) {
|
public ResourceProviderExtension(RestfulServerExtension theRestfulServerExtension, T theProvider) {
|
||||||
|
Validate.notNull(theRestfulServerExtension);
|
||||||
|
Validate.notNull(theProvider);
|
||||||
myRestfulServerExtension = theRestfulServerExtension;
|
myRestfulServerExtension = theRestfulServerExtension;
|
||||||
myProvider = theProvider;
|
myProvider = theProvider;
|
||||||
}
|
}
|
||||||
|
@ -46,4 +49,9 @@ public class ResourceProviderExtension implements BeforeEachCallback, AfterEachC
|
||||||
public void beforeEach(ExtensionContext context) {
|
public void beforeEach(ExtensionContext context) {
|
||||||
myRestfulServerExtension.getRestfulServer().registerProvider(myProvider);
|
myRestfulServerExtension.getRestfulServer().registerProvider(myProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T getProvider() {
|
||||||
|
return myProvider;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,6 +234,10 @@ public class RestfulServerExtension implements BeforeEachCallback, AfterEachCall
|
||||||
return "http://localhost:" + myPort;
|
return "http://localhost:" + myPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void unregisterAllInterceptors() {
|
||||||
|
myServlet.getInterceptorService().unregisterAllInterceptors();
|
||||||
|
}
|
||||||
|
|
||||||
@Interceptor
|
@Interceptor
|
||||||
private class ListenerExtension {
|
private class ListenerExtension {
|
||||||
|
|
||||||
|
|
|
@ -3,3 +3,6 @@
|
||||||
2021, gt ge ne,2020,
|
2021, gt ge ne,2020,
|
||||||
2020, lt le ne,2021,
|
2020, lt le ne,2021,
|
||||||
2021-01-01, ne gt ge,2020
|
2021-01-01, ne gt ge,2020
|
||||||
|
1965-08-09, ne gt ge, 1918-11-11
|
||||||
|
1965-08-09, eq le ge, 1965-08-09
|
||||||
|
1965-08-09, ne lt le, 2020-12-08
|
||||||
|
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,9 @@ package org.hl7.fhir.common.hapi.validation.support;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
import org.hl7.fhir.exceptions.TerminologyServiceException;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -18,9 +19,11 @@ import javax.annotation.Nullable;
|
||||||
* in order to specify that unknown code systems should be allowed.
|
* in order to specify that unknown code systems should be allowed.
|
||||||
*/
|
*/
|
||||||
public class UnknownCodeSystemWarningValidationSupport extends BaseValidationSupport {
|
public class UnknownCodeSystemWarningValidationSupport extends BaseValidationSupport {
|
||||||
public static final boolean ALLOW_NON_EXISTENT_CODE_SYSTEM_DEFAULT = false;
|
private static final Logger ourLog = LoggerFactory.getLogger(UnknownCodeSystemWarningValidationSupport.class);
|
||||||
|
|
||||||
private boolean myAllowNonExistentCodeSystem = ALLOW_NON_EXISTENT_CODE_SYSTEM_DEFAULT;
|
public static final IssueSeverity DEFAULT_SEVERITY = IssueSeverity.ERROR;
|
||||||
|
|
||||||
|
private IssueSeverity myNonExistentCodeSystemSeverity = DEFAULT_SEVERITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -34,17 +37,39 @@ public class UnknownCodeSystemWarningValidationSupport extends BaseValidationSup
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCodeSystemSupported(ValidationSupportContext theValidationSupportContext, String theSystem) {
|
||||||
|
return canValidateCodeSystem(theValidationSupportContext, theSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeValidationResult validateCode(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, String theValueSetUrl) {
|
||||||
|
// filters out error/fatal
|
||||||
|
if (!canValidateCodeSystem(theValidationSupportContext, theCodeSystem)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeValidationResult result = new CodeValidationResult()
|
||||||
|
.setSeverity(myNonExistentCodeSystemSeverity); // will be warning or info
|
||||||
|
|
||||||
|
result.setMessage("No issues detected during validation");
|
||||||
|
|
||||||
|
switch (myNonExistentCodeSystemSeverity) {
|
||||||
|
case INFORMATION:
|
||||||
|
// for warnings, we don't set the code
|
||||||
|
// cause if we do, the severity is stripped out
|
||||||
|
// (see VersionSpecificWorkerContextWrapper.convertValidationResult)
|
||||||
|
result.setCode(theCode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public CodeValidationResult validateCodeInValueSet(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, @Nonnull IBaseResource theValueSet) {
|
public CodeValidationResult validateCodeInValueSet(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, @Nonnull IBaseResource theValueSet) {
|
||||||
if (!myAllowNonExistentCodeSystem) {
|
if (!canValidateCodeSystem(theValidationSupportContext, theCodeSystem)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (theCodeSystem == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
IBaseResource codeSystem = theValidationSupportContext.getRootValidationSupport().fetchCodeSystem(theCodeSystem);
|
|
||||||
if (codeSystem != null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +79,60 @@ public class UnknownCodeSystemWarningValidationSupport extends BaseValidationSup
|
||||||
.setMessage("Code " + theCodeSystem + "#" + theCode + " was not checked because the CodeSystem is not available");
|
.setMessage("Code " + theCodeSystem + "#" + theCode + " was not checked because the CodeSystem is not available");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if non existent code systems will still validate.
|
||||||
|
* False if they will throw errors.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean allowNonExistentCodeSystems() {
|
||||||
|
switch (myNonExistentCodeSystemSeverity) {
|
||||||
|
case ERROR:
|
||||||
|
case FATAL:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
ourLog.info("Unknown issue severity " + myNonExistentCodeSystemSeverity.name()
|
||||||
|
+ ". Treating as INFO/WARNING");
|
||||||
|
case WARNING:
|
||||||
|
case INFORMATION:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canValidateCodeSystem(ValidationSupportContext theValidationSupportContext,
|
||||||
|
String theCodeSystem) {
|
||||||
|
if (!allowNonExistentCodeSystems()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (theCodeSystem == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
IBaseResource codeSystem = theValidationSupportContext.getRootValidationSupport().fetchCodeSystem(theCodeSystem);
|
||||||
|
if (codeSystem != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to allow, code system violations will be flagged with Warning by default.
|
||||||
|
* Use setNonExistentCodeSystemSeverity instead.
|
||||||
|
*
|
||||||
|
* @param theAllowNonExistentCodeSystem
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setAllowNonExistentCodeSystem(boolean theAllowNonExistentCodeSystem) {
|
public void setAllowNonExistentCodeSystem(boolean theAllowNonExistentCodeSystem) {
|
||||||
myAllowNonExistentCodeSystem = theAllowNonExistentCodeSystem;
|
if (theAllowNonExistentCodeSystem) {
|
||||||
|
setNonExistentCodeSystemSeverity(IssueSeverity.WARNING);
|
||||||
|
} else {
|
||||||
|
setNonExistentCodeSystemSeverity(IssueSeverity.ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the non-existent code system severity.
|
||||||
|
* @param theSeverity
|
||||||
|
*/
|
||||||
|
public void setNonExistentCodeSystemSeverity(IssueSeverity theSeverity) {
|
||||||
|
myNonExistentCodeSystemSeverity = theSeverity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,27 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.rest.annotation.Create;
|
import ca.uhn.fhir.rest.annotation.Create;
|
||||||
import ca.uhn.fhir.rest.annotation.Delete;
|
import ca.uhn.fhir.rest.annotation.Delete;
|
||||||
|
import ca.uhn.fhir.rest.annotation.GraphQL;
|
||||||
|
import ca.uhn.fhir.rest.annotation.GraphQLQueryBody;
|
||||||
|
import ca.uhn.fhir.rest.annotation.GraphQLQueryUrl;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Search;
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
import ca.uhn.fhir.rest.param.StringParam;
|
import ca.uhn.fhir.rest.param.StringParam;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
import ca.uhn.fhir.test.utilities.HttpClientExtension;
|
||||||
|
import ca.uhn.fhir.test.utilities.server.ResourceProviderExtension;
|
||||||
|
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
import ca.uhn.fhir.validation.IValidationContext;
|
import ca.uhn.fhir.validation.IValidationContext;
|
||||||
import ca.uhn.fhir.validation.IValidatorModule;
|
import ca.uhn.fhir.validation.IValidatorModule;
|
||||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||||
|
@ -28,29 +34,23 @@ import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
|
import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
|
||||||
import org.hl7.fhir.r4.model.IdType;
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
import org.hl7.fhir.r4.model.Narrative;
|
import org.hl7.fhir.r4.model.Narrative;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
@ -59,23 +59,27 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
public class RequestValidatingInterceptorR4Test {
|
public class RequestValidatingInterceptorR4Test {
|
||||||
private static CloseableHttpClient ourClient;
|
|
||||||
|
|
||||||
private static FhirContext ourCtx = FhirContext.forR4();
|
|
||||||
private static boolean ourLastRequestWasSearch;
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RequestValidatingInterceptorR4Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RequestValidatingInterceptorR4Test.class);
|
||||||
|
@RegisterExtension
|
||||||
|
static HttpClientExtension ourClient = new HttpClientExtension();
|
||||||
|
private static final FhirContext ourCtx = FhirContext.forR4Cached();
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
@Order(0)
|
||||||
|
static RestfulServerExtension ourServlet = new RestfulServerExtension(ourCtx);
|
||||||
|
@RegisterExtension
|
||||||
|
@Order(1)
|
||||||
|
static ResourceProviderExtension<PatientProvider> ourProvider = new ResourceProviderExtension<>(ourServlet, new PatientProvider());
|
||||||
|
private static boolean ourLastRequestWasSearch;
|
||||||
private static int ourPort;
|
private static int ourPort;
|
||||||
|
|
||||||
private static Server ourServer;
|
|
||||||
|
|
||||||
private static RestfulServer ourServlet;
|
|
||||||
|
|
||||||
private RequestValidatingInterceptor myInterceptor;
|
private RequestValidatingInterceptor myInterceptor;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void before() {
|
public void before() {
|
||||||
|
ourProvider.getProvider().ourLastGraphQlQueryGet = null;
|
||||||
|
ourProvider.getProvider().ourLastGraphQlQueryPost = null;
|
||||||
ourLastRequestWasSearch = false;
|
ourLastRequestWasSearch = false;
|
||||||
ourServlet.getInterceptorService().unregisterAllInterceptors();
|
ourServlet.unregisterAllInterceptors();
|
||||||
|
|
||||||
myInterceptor = new RequestValidatingInterceptor();
|
myInterceptor = new RequestValidatingInterceptor();
|
||||||
// myInterceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
// myInterceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||||
|
@ -84,6 +88,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
// myInterceptor.setResponseHeaderValue(RequestValidatingInterceptor.DEFAULT_RESPONSE_HEADER_VALUE);
|
// myInterceptor.setResponseHeaderValue(RequestValidatingInterceptor.DEFAULT_RESPONSE_HEADER_VALUE);
|
||||||
|
|
||||||
ourServlet.registerInterceptor(myInterceptor);
|
ourServlet.registerInterceptor(myInterceptor);
|
||||||
|
ourPort = ourServlet.getPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -100,7 +105,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -113,6 +118,41 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
assertThat(responseContent, not(containsString("<severity value=\"error\"/>")));
|
assertThat(responseContent, not(containsString("<severity value=\"error\"/>")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGraphQlRequestResponse_GET() throws IOException {
|
||||||
|
HttpGet request = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escapeUrlParam("{name}"));
|
||||||
|
|
||||||
|
try (CloseableHttpResponse status = ourClient.getClient().execute(request)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
|
||||||
|
ourLog.info("Response was:\n{}", status);
|
||||||
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertEquals("{\"name\":{\"family\": \"foo\"}}", responseContent);
|
||||||
|
assertEquals("{name}", ourProvider.getProvider().ourLastGraphQlQueryGet);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGraphQlRequestResponse_POST() throws IOException {
|
||||||
|
HttpPost request = new HttpPost("http://localhost:" + ourPort + "/Patient/123/$graphql");
|
||||||
|
request.setEntity(new StringEntity("{\"query\": \"{name}\"}", ContentType.APPLICATION_JSON));
|
||||||
|
|
||||||
|
try (CloseableHttpResponse status = ourClient.getClient().execute(request)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
|
||||||
|
ourLog.info("Response was:\n{}", status);
|
||||||
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertEquals("{\"name\":{\"family\": \"foo\"}}", responseContent);
|
||||||
|
assertEquals("{name}", ourProvider.getProvider().ourLastGraphQlQueryPost);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateJsonInvalidNoValidatorsSpecified() throws Exception {
|
public void testCreateJsonInvalidNoValidatorsSpecified() throws Exception {
|
||||||
myInterceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
myInterceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
||||||
|
@ -126,7 +166,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -136,7 +176,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
|
|
||||||
assertEquals(422, status.getStatusLine().getStatusCode());
|
assertEquals(422, status.getStatusLine().getStatusCode());
|
||||||
assertThat(status.toString(), containsString("X-FHIR-Request-Validation"));
|
assertThat(status.toString(), containsString("X-FHIR-Request-Validation"));
|
||||||
assertThat(responseContent, containsString("\"severity\":\"error\""));
|
assertThat(responseContent, containsString("\"severity\": \"error\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -150,7 +190,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -176,7 +216,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -188,8 +228,6 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
assertThat(status.toString(), (containsString("X-FHIR-Request-Validation: NO ISSUES")));
|
assertThat(status.toString(), (containsString("X-FHIR-Request-Validation: NO ISSUES")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateXmlPayloadWithXxeDirective_InstanceValidator() throws IOException {
|
public void testValidateXmlPayloadWithXxeDirective_InstanceValidator() throws IOException {
|
||||||
IValidatorModule module = new FhirInstanceValidator(ourCtx);
|
IValidatorModule module = new FhirInstanceValidator(ourCtx);
|
||||||
|
@ -213,7 +251,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
try (CloseableHttpResponse status = ourClient.execute(httpPost)) {
|
try (CloseableHttpResponse status = ourClient.getClient().execute(httpPost)) {
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
|
||||||
ourLog.info("Response was:\n{}", status);
|
ourLog.info("Response was:\n{}", status);
|
||||||
|
@ -225,7 +263,6 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateXmlInvalidInstanceValidator() throws Exception {
|
public void testCreateXmlInvalidInstanceValidator() throws Exception {
|
||||||
IValidatorModule module = new FhirInstanceValidator(ourCtx);
|
IValidatorModule module = new FhirInstanceValidator(ourCtx);
|
||||||
|
@ -242,7 +279,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
try (CloseableHttpResponse status = ourClient.execute(httpPost)) {
|
try (CloseableHttpResponse status = ourClient.getClient().execute(httpPost)) {
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
|
||||||
ourLog.info("Response was:\n{}", status);
|
ourLog.info("Response was:\n{}", status);
|
||||||
|
@ -266,7 +303,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -293,7 +330,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -305,7 +342,6 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
assertThat(status.toString(), containsString("X-FHIR-Request-Validation: {\"resourceType\":\"OperationOutcome"));
|
assertThat(status.toString(), containsString("X-FHIR-Request-Validation: {\"resourceType\":\"OperationOutcome"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void testInterceptorExceptionNpeNoIgnore() throws Exception {
|
public void testInterceptorExceptionNpeNoIgnore() throws Exception {
|
||||||
|
@ -317,14 +353,14 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
myInterceptor.setIgnoreValidatorExceptions(false);
|
myInterceptor.setIgnoreValidatorExceptions(false);
|
||||||
|
|
||||||
Mockito.doThrow(new NullPointerException("SOME MESSAGE")).when(module).validateResource(Mockito.any(IValidationContext.class));
|
Mockito.doThrow(new NullPointerException("SOME MESSAGE")).when(module).validateResource(Mockito.any(IValidationContext.class));
|
||||||
|
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||||
|
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -347,14 +383,14 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
myInterceptor.setIgnoreValidatorExceptions(true);
|
myInterceptor.setIgnoreValidatorExceptions(true);
|
||||||
|
|
||||||
Mockito.doThrow(NullPointerException.class).when(module).validateResource(Mockito.any(IValidationContext.class));
|
Mockito.doThrow(NullPointerException.class).when(module).validateResource(Mockito.any(IValidationContext.class));
|
||||||
|
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||||
|
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -377,14 +413,14 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
myInterceptor.setIgnoreValidatorExceptions(false);
|
myInterceptor.setIgnoreValidatorExceptions(false);
|
||||||
|
|
||||||
Mockito.doThrow(new InternalErrorException("FOO")).when(module).validateResource(Mockito.any(IValidationContext.class));
|
Mockito.doThrow(new InternalErrorException("FOO")).when(module).validateResource(Mockito.any(IValidationContext.class));
|
||||||
|
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||||
|
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -407,14 +443,14 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
myInterceptor.setIgnoreValidatorExceptions(true);
|
myInterceptor.setIgnoreValidatorExceptions(true);
|
||||||
|
|
||||||
Mockito.doThrow(InternalErrorException.class).when(module).validateResource(Mockito.any(IValidationContext.class));
|
Mockito.doThrow(InternalErrorException.class).when(module).validateResource(Mockito.any(IValidationContext.class));
|
||||||
|
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||||
|
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -437,7 +473,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
httpPost.setEntity(new StringEntity(encoded, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -459,7 +495,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
|
|
||||||
HttpDelete httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient/123");
|
HttpDelete httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient/123");
|
||||||
|
|
||||||
CloseableHttpResponse status = ourClient.execute(httpDelete);
|
CloseableHttpResponse status = ourClient.getClient().execute(httpDelete);
|
||||||
try {
|
try {
|
||||||
ourLog.info("Response was:\n{}", status);
|
ourLog.info("Response was:\n{}", status);
|
||||||
|
|
||||||
|
@ -479,7 +515,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
// This header caused a crash
|
// This header caused a crash
|
||||||
httpGet.addHeader("Content-Type", "application/xml+fhir");
|
httpGet.addHeader("Content-Type", "application/xml+fhir");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
HttpResponse status = ourClient.getClient().execute(httpGet);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -495,7 +531,7 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
public void testSearch() throws Exception {
|
public void testSearch() throws Exception {
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -508,36 +544,13 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
assertEquals(true, ourLastRequestWasSearch);
|
assertEquals(true, ourLastRequestWasSearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
JettyUtil.closeServer(ourServer);
|
|
||||||
TestUtil.randomizeLocaleAndTimezone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
ourServer = new Server(0);
|
|
||||||
|
|
||||||
PatientProvider patientProvider = new PatientProvider();
|
|
||||||
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
|
||||||
ourServlet = new RestfulServer(ourCtx);
|
|
||||||
ourServlet.setResourceProviders(patientProvider);
|
|
||||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
|
||||||
ourServer.setHandler(proxyHandler);
|
|
||||||
JettyUtil.startServer(ourServer);
|
|
||||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
|
||||||
|
|
||||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
|
||||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
|
||||||
builder.setConnectionManager(connectionManager);
|
|
||||||
ourClient = builder.build();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PatientProvider implements IResourceProvider {
|
public static class PatientProvider implements IResourceProvider {
|
||||||
|
|
||||||
|
public String ourLastGraphQlQueryGet;
|
||||||
|
public String ourLastGraphQlQueryPost;
|
||||||
|
|
||||||
|
private IBaseResource myReturnResource;
|
||||||
|
|
||||||
@Create()
|
@Create()
|
||||||
public MethodOutcome createPatient(@ResourceParam Patient thePatient, @IdParam IdType theIdParam) {
|
public MethodOutcome createPatient(@ResourceParam Patient thePatient, @IdParam IdType theIdParam) {
|
||||||
return new MethodOutcome(new IdDt("Patient/001/_history/002"));
|
return new MethodOutcome(new IdDt("Patient/001/_history/002"));
|
||||||
|
@ -548,17 +561,45 @@ public class RequestValidatingInterceptorR4Test {
|
||||||
return new MethodOutcome(theId.withVersion("2"));
|
return new MethodOutcome(theId.withVersion("2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GraphQL(type = RequestTypeEnum.GET)
|
||||||
|
public String graphQLGet(@IdParam IIdType theId, @GraphQLQueryUrl String theQueryUrl) {
|
||||||
|
ourLastGraphQlQueryGet = theQueryUrl;
|
||||||
|
return "{\"name\":{\"family\": \"foo\"}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GraphQL(type = RequestTypeEnum.POST)
|
||||||
|
public String graphQLPost(@IdParam IIdType theId, @GraphQLQueryBody String theQueryUrl) {
|
||||||
|
ourLastGraphQlQueryPost = theQueryUrl;
|
||||||
|
return "{\"name\":{\"family\": \"foo\"}}";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<? extends IBaseResource> getResourceType() {
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
return Patient.class;
|
return Patient.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Search
|
public void setReturnResource(IBaseResource theReturnResource) {
|
||||||
public List<IResource> search(@OptionalParam(name = "foo") StringParam theString) {
|
myReturnResource = theReturnResource;
|
||||||
ourLastRequestWasSearch = true;
|
|
||||||
return new ArrayList<IResource>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Search
|
||||||
|
public ArrayList<IBaseResource> search(@OptionalParam(name = "foo") StringParam theString) {
|
||||||
|
ourLastRequestWasSearch = true;
|
||||||
|
ArrayList<IBaseResource> retVal = new ArrayList<>();
|
||||||
|
if (myReturnResource != null) {
|
||||||
|
myReturnResource.setId("1");
|
||||||
|
retVal.add(myReturnResource);
|
||||||
|
myReturnResource = null;
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void afterClassClearContext() throws Exception {
|
||||||
|
TestUtil.randomizeLocaleAndTimezone();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,13 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.rest.annotation.Delete;
|
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Search;
|
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.param.StringParam;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
import ca.uhn.fhir.test.utilities.HttpClientExtension;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.test.utilities.server.ResourceProviderExtension;
|
||||||
|
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
|
||||||
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
import ca.uhn.fhir.validation.IValidationContext;
|
import ca.uhn.fhir.validation.IValidationContext;
|
||||||
import ca.uhn.fhir.validation.IValidatorModule;
|
import ca.uhn.fhir.validation.IValidatorModule;
|
||||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||||
|
@ -22,28 +17,22 @@ import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpDelete;
|
import org.apache.http.client.methods.HttpDelete;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
|
||||||
import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
|
import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
|
||||||
import org.hl7.fhir.r4.model.IdType;
|
|
||||||
import org.hl7.fhir.r4.model.Narrative;
|
import org.hl7.fhir.r4.model.Narrative;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
@ -54,20 +43,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
public class ResponseValidatingInterceptorR4Test {
|
public class ResponseValidatingInterceptorR4Test {
|
||||||
public static IBaseResource myReturnResource;
|
|
||||||
|
|
||||||
private static CloseableHttpClient ourClient;
|
|
||||||
private static FhirContext ourCtx = FhirContext.forR4();
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResponseValidatingInterceptorR4Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResponseValidatingInterceptorR4Test.class);
|
||||||
|
@RegisterExtension
|
||||||
|
static HttpClientExtension ourClient = new HttpClientExtension();
|
||||||
|
private static final FhirContext ourCtx = FhirContext.forR4Cached();
|
||||||
|
@RegisterExtension
|
||||||
|
@Order(0)
|
||||||
|
static RestfulServerExtension ourServlet = new RestfulServerExtension(ourCtx);
|
||||||
|
@RegisterExtension
|
||||||
|
@Order(1)
|
||||||
|
static ResourceProviderExtension<RequestValidatingInterceptorR4Test.PatientProvider> ourProvider = new ResourceProviderExtension<>(ourServlet, new RequestValidatingInterceptorR4Test.PatientProvider());
|
||||||
private static int ourPort;
|
private static int ourPort;
|
||||||
private static Server ourServer;
|
|
||||||
private static RestfulServer ourServlet;
|
|
||||||
private ResponseValidatingInterceptor myInterceptor;
|
private ResponseValidatingInterceptor myInterceptor;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void before() {
|
public void before() {
|
||||||
myReturnResource = null;
|
ourProvider.getProvider().setReturnResource(null);
|
||||||
ourServlet.getInterceptorService().unregisterAllInterceptors();
|
ourProvider.getProvider().ourLastGraphQlQueryGet = null;
|
||||||
|
ourProvider.getProvider().ourLastGraphQlQueryPost = null;
|
||||||
|
ourServlet.unregisterAllInterceptors();
|
||||||
|
|
||||||
myInterceptor = new ResponseValidatingInterceptor();
|
myInterceptor = new ResponseValidatingInterceptor();
|
||||||
// myInterceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
// myInterceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||||
|
@ -76,15 +70,16 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
// myInterceptor.setResponseHeaderValue(RequestValidatingInterceptor.DEFAULT_RESPONSE_HEADER_VALUE);
|
// myInterceptor.setResponseHeaderValue(RequestValidatingInterceptor.DEFAULT_RESPONSE_HEADER_VALUE);
|
||||||
|
|
||||||
ourServlet.registerInterceptor(myInterceptor);
|
ourServlet.registerInterceptor(myInterceptor);
|
||||||
|
ourPort = ourServlet.getPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void testInterceptorExceptionNpeNoIgnore() throws Exception {
|
public void testInterceptorExceptionNpeNoIgnore() throws Exception {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
myInterceptor.setAddResponseHeaderOnSeverity(null);
|
myInterceptor.setAddResponseHeaderOnSeverity(null);
|
||||||
myInterceptor.setFailOnSeverity(null);
|
myInterceptor.setFailOnSeverity(null);
|
||||||
|
@ -94,9 +89,9 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
myInterceptor.setIgnoreValidatorExceptions(false);
|
myInterceptor.setIgnoreValidatorExceptions(false);
|
||||||
|
|
||||||
Mockito.doThrow(new NullPointerException("SOME MESSAGE")).when(module).validateResource(Mockito.any(IValidationContext.class));
|
Mockito.doThrow(new NullPointerException("SOME MESSAGE")).when(module).validateResource(Mockito.any(IValidationContext.class));
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -105,7 +100,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
assertEquals(500, status.getStatusLine().getStatusCode());
|
assertEquals(500, status.getStatusLine().getStatusCode());
|
||||||
assertThat(responseContent, containsString("<diagnostics value=\"SOME MESSAGE\"/>"));
|
assertThat(responseContent, containsString("\"diagnostics\": \"SOME MESSAGE\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -114,7 +109,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
myInterceptor.setAddResponseHeaderOnSeverity(null);
|
myInterceptor.setAddResponseHeaderOnSeverity(null);
|
||||||
myInterceptor.setFailOnSeverity(null);
|
myInterceptor.setFailOnSeverity(null);
|
||||||
|
@ -124,9 +119,9 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
myInterceptor.setIgnoreValidatorExceptions(true);
|
myInterceptor.setIgnoreValidatorExceptions(true);
|
||||||
|
|
||||||
Mockito.doThrow(NullPointerException.class).when(module).validateResource(Mockito.any(IValidationContext.class));
|
Mockito.doThrow(NullPointerException.class).when(module).validateResource(Mockito.any(IValidationContext.class));
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -144,7 +139,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
myInterceptor.setAddResponseHeaderOnSeverity(null);
|
myInterceptor.setAddResponseHeaderOnSeverity(null);
|
||||||
myInterceptor.setFailOnSeverity(null);
|
myInterceptor.setFailOnSeverity(null);
|
||||||
|
@ -154,9 +149,9 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
myInterceptor.setIgnoreValidatorExceptions(false);
|
myInterceptor.setIgnoreValidatorExceptions(false);
|
||||||
|
|
||||||
Mockito.doThrow(new InternalErrorException("FOO")).when(module).validateResource(Mockito.any(IValidationContext.class));
|
Mockito.doThrow(new InternalErrorException("FOO")).when(module).validateResource(Mockito.any(IValidationContext.class));
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -165,7 +160,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
assertEquals(500, status.getStatusLine().getStatusCode());
|
assertEquals(500, status.getStatusLine().getStatusCode());
|
||||||
assertThat(responseContent, containsString("<diagnostics value=\"FOO\"/>"));
|
assertThat(responseContent, containsString("\"diagnostics\": \"FOO\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -174,7 +169,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
myInterceptor.setAddResponseHeaderOnSeverity(null);
|
myInterceptor.setAddResponseHeaderOnSeverity(null);
|
||||||
myInterceptor.setFailOnSeverity(null);
|
myInterceptor.setFailOnSeverity(null);
|
||||||
|
@ -184,9 +179,9 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
myInterceptor.setIgnoreValidatorExceptions(true);
|
myInterceptor.setIgnoreValidatorExceptions(true);
|
||||||
|
|
||||||
Mockito.doThrow(InternalErrorException.class).when(module).validateResource(Mockito.any(IValidationContext.class));
|
Mockito.doThrow(InternalErrorException.class).when(module).validateResource(Mockito.any(IValidationContext.class));
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -198,7 +193,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
assertThat(status.toString(), not(containsString("X-FHIR-Response-Validation")));
|
assertThat(status.toString(), not(containsString("X-FHIR-Response-Validation")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for #345
|
* Test for #345
|
||||||
*/
|
*/
|
||||||
|
@ -209,7 +204,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
|
|
||||||
HttpDelete httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient/123");
|
HttpDelete httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient/123");
|
||||||
|
|
||||||
CloseableHttpResponse status = ourClient.execute(httpDelete);
|
CloseableHttpResponse status = ourClient.getClient().execute(httpDelete);
|
||||||
try {
|
try {
|
||||||
ourLog.info("Response was:\n{}", status);
|
ourLog.info("Response was:\n{}", status);
|
||||||
|
|
||||||
|
@ -220,6 +215,40 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGraphQlRequestResponse_GET() throws IOException {
|
||||||
|
HttpGet request = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escapeUrlParam("{name}"));
|
||||||
|
|
||||||
|
try (CloseableHttpResponse status = ourClient.getClient().execute(request)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
|
||||||
|
ourLog.info("Response was:\n{}", status);
|
||||||
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertEquals("{\"name\":{\"family\": \"foo\"}}", responseContent);
|
||||||
|
assertEquals("{name}", ourProvider.getProvider().ourLastGraphQlQueryGet);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGraphQlRequestResponse_POST() throws IOException {
|
||||||
|
HttpPost request = new HttpPost("http://localhost:" + ourPort + "/Patient/123/$graphql");
|
||||||
|
request.setEntity(new StringEntity("{\"query\": \"{name}\"}", ContentType.APPLICATION_JSON));
|
||||||
|
|
||||||
|
try (CloseableHttpResponse status = ourClient.getClient().execute(request)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
|
||||||
|
ourLog.info("Response was:\n{}", status);
|
||||||
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertEquals("{\"name\":{\"family\": \"foo\"}}", responseContent);
|
||||||
|
assertEquals("{name}", ourProvider.getProvider().ourLastGraphQlQueryPost);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLongHeaderTruncated() throws Exception {
|
public void testLongHeaderTruncated() throws Exception {
|
||||||
|
@ -233,12 +262,12 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
patient.addContact().setGender(AdministrativeGender.MALE);
|
patient.addContact().setGender(AdministrativeGender.MALE);
|
||||||
}
|
}
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
|
|
||||||
{
|
{
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -252,7 +281,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
myInterceptor.setMaximumHeaderLength(100);
|
myInterceptor.setMaximumHeaderLength(100);
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -273,11 +302,11 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
patient.getText().setDiv(new XhtmlNode().setValue("<div>AA</div>")).setStatus(Narrative.NarrativeStatus.GENERATED);
|
patient.getText().setDiv(new XhtmlNode().setValue("<div>AA</div>")).setStatus(Narrative.NarrativeStatus.GENERATED);
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -287,23 +316,20 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
assertThat(status.toString(), (containsString(
|
assertThat(status.toString(), (containsString(
|
||||||
"X-FHIR-Response-Validation: {\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"information\",\"code\":\"informational\",\"diagnostics\":\"No issues detected\"}]}")));
|
"X-FHIR-Response-Validation: {\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"information\",\"code\":\"informational\",\"diagnostics\":\"No issues detected\"}]}")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Ignored until #264 is fixed
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchJsonInvalidNoValidatorsSpecified() throws Exception {
|
public void testSearchJsonInvalidNoValidatorsSpecified() throws Exception {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
patient.addContact().addRelationship().setText("FOO");
|
patient.addContact().addRelationship().setText("FOO");
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -312,7 +338,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
assertEquals(422, status.getStatusLine().getStatusCode());
|
assertEquals(422, status.getStatusLine().getStatusCode());
|
||||||
assertThat(responseContent, containsString("<severity value=\"error\"/>"));
|
assertThat(responseContent, containsString("\"severity\": \"error\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -321,11 +347,11 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
patient.getText().setDiv(new XhtmlNode().setValue("<div>AA</div>")).setStatus(Narrative.NarrativeStatus.GENERATED);
|
patient.getText().setDiv(new XhtmlNode().setValue("<div>AA</div>")).setStatus(Narrative.NarrativeStatus.GENERATED);
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -346,11 +372,11 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
patient.getText().setDiv(new XhtmlNode().setValue("<div>AA</div>")).setStatus(Narrative.NarrativeStatus.GENERATED);
|
patient.getText().setDiv(new XhtmlNode().setValue("<div>AA</div>")).setStatus(Narrative.NarrativeStatus.GENERATED);
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -372,11 +398,11 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
patient.addContact().addRelationship().setText("FOO");
|
patient.addContact().addRelationship().setText("FOO");
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -397,11 +423,11 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
patient.addContact().addRelationship().setText("FOO");
|
patient.addContact().addRelationship().setText("FOO");
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -410,7 +436,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
assertEquals(422, status.getStatusLine().getStatusCode());
|
assertEquals(422, status.getStatusLine().getStatusCode());
|
||||||
assertThat(responseContent, Matchers.containsString("<severity value=\"error\"/>"));
|
assertThat(responseContent, Matchers.containsString("\"severity\": \"error\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -419,11 +445,11 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
patient.getText().setDiv(new XhtmlNode().setValue("<div>AA</div>")).setStatus(Narrative.NarrativeStatus.GENERATED);
|
patient.getText().setDiv(new XhtmlNode().setValue("<div>AA</div>")).setStatus(Narrative.NarrativeStatus.GENERATED);
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
patient.setGender(AdministrativeGender.MALE);
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
myReturnResource = patient;
|
ourProvider.getProvider().setReturnResource(patient);
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -443,7 +469,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
myInterceptor.setResponseHeaderValueNoIssues("No issues");
|
myInterceptor.setResponseHeaderValueNoIssues("No issues");
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/metadata");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/metadata");
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
@ -463,7 +489,7 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
myInterceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
myInterceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
||||||
|
|
||||||
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/metadata?_pretty=true");
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/metadata?_pretty=true");
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
HttpResponse status = ourClient.getClient().execute(httpPost);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
ourLog.info(responseContent);
|
ourLog.info(responseContent);
|
||||||
|
@ -476,56 +502,4 @@ public class ResponseValidatingInterceptorR4Test {
|
||||||
assertThat(status.toString(), (containsString("X-FHIR-Response-Validation")));
|
assertThat(status.toString(), (containsString("X-FHIR-Response-Validation")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void afterClassClearContext() throws Exception {
|
|
||||||
JettyUtil.closeServer(ourServer);
|
|
||||||
TestUtil.randomizeLocaleAndTimezone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void beforeClass() throws Exception {
|
|
||||||
ourServer = new Server(0);
|
|
||||||
|
|
||||||
PatientProvider patientProvider = new PatientProvider();
|
|
||||||
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
|
||||||
ourServlet = new RestfulServer(ourCtx);
|
|
||||||
ourServlet.setResourceProviders(patientProvider);
|
|
||||||
ourServlet.setDefaultResponseEncoding(EncodingEnum.XML);
|
|
||||||
|
|
||||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
|
||||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
|
||||||
ourServer.setHandler(proxyHandler);
|
|
||||||
JettyUtil.startServer(ourServer);
|
|
||||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
|
||||||
|
|
||||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
|
||||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
|
||||||
builder.setConnectionManager(connectionManager);
|
|
||||||
ourClient = builder.build();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PatientProvider implements IResourceProvider {
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
public MethodOutcome delete(@IdParam IdType theId) {
|
|
||||||
return new MethodOutcome(theId.withVersion("2"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends IBaseResource> getResourceType() {
|
|
||||||
return Patient.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Search
|
|
||||||
public ArrayList<IBaseResource> search(@OptionalParam(name = "foo") StringParam theString) {
|
|
||||||
ArrayList<IBaseResource> retVal = new ArrayList<>();
|
|
||||||
myReturnResource.setId("1");
|
|
||||||
retVal.add(myReturnResource);
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -58,37 +58,37 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-structures-dstu3</artifactId>
|
<artifactId>hapi-fhir-structures-dstu3</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
|
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-structures-r4</artifactId>
|
<artifactId>hapi-fhir-structures-r4</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-structures-r5</artifactId>
|
<artifactId>hapi-fhir-structures-r5</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
|
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-validation-resources-r4</artifactId>
|
<artifactId>hapi-fhir-validation-resources-r4</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.velocity</groupId>
|
<groupId>org.apache.velocity</groupId>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
4
pom.xml
4
pom.xml
|
@ -6,7 +6,7 @@
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<name>HAPI-FHIR</name>
|
<name>HAPI-FHIR</name>
|
||||||
<description>An open-source implementation of the FHIR specification in Java.</description>
|
<description>An open-source implementation of the FHIR specification in Java.</description>
|
||||||
<url>https://hapifhir.io</url>
|
<url>https://hapifhir.io</url>
|
||||||
|
@ -2913,7 +2913,7 @@
|
||||||
<profile>
|
<profile>
|
||||||
<id>FASTINSTALL</id>
|
<id>FASTINSTALL</id>
|
||||||
<properties>
|
<properties>
|
||||||
<maven.test.skip>true</maven.test.skip>
|
<skipTests>true</skipTests>
|
||||||
</properties>
|
</properties>
|
||||||
<!-- Profile for a quick local mvn install after a git pull.
|
<!-- Profile for a quick local mvn install after a git pull.
|
||||||
We assume upstream ran these checks as part of the build. -->
|
We assume upstream ran these checks as part of the build. -->
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>5.7.0-PRE2-SNAPSHOT</version>
|
<version>5.7.0-PRE3-SNAPSHOT</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue