- * Defaults to 2000 + * Defaults to 100 *
*/ public int getDeferIndexingForCodesystemsOfSize() { @@ -409,7 +409,7 @@ public class DaoConfig { * the code system will be indexed later in an incremental process in order to * avoid overwhelming Lucene with a huge number of codes in a single operation. *- * Defaults to 2000 + * Defaults to 100 *
*/ public void setDeferIndexingForCodesystemsOfSize(int theDeferIndexingForCodesystemsOfSize) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IResultIterator.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IResultIterator.java index ce4795e9630..1b84f581849 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IResultIterator.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IResultIterator.java @@ -29,4 +29,6 @@ public interface IResultIterator extends Iterator implements IFhirResourceDaoConceptMap {
@Autowired
private ITermReadSvc myHapiTerminologySvc;
@@ -166,7 +171,7 @@ public class FhirResourceDaoConceptMapDstu3 extends BaseHapiFhirResourceDao implements IFhirResourceDaoValueSet {
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoValueSetDstu3.class);
@@ -420,7 +423,7 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao {
- counter.addAndGet(doExpungeEverythingQuery("UPDATE " + ResourceHistoryTable.class.getSimpleName() + " d SET d.myForcedId = null"));
- counter.addAndGet(doExpungeEverythingQuery("UPDATE " + ResourceTable.class.getSimpleName() + " d SET d.myForcedId = null"));
counter.addAndGet(doExpungeEverythingQuery("UPDATE " + TermCodeSystem.class.getSimpleName() + " d SET d.myCurrentVersion = null"));
return null;
});
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderDate.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderDate.java
index 6ad65712e1d..37274a1d07a 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderDate.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderDate.java
@@ -39,13 +39,17 @@ import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
@Component
@Scope("prototype")
public class PredicateBuilderDate extends BasePredicateBuilder implements IPredicateBuilder {
private static final Logger ourLog = LoggerFactory.getLogger(PredicateBuilderDate.class);
+ private Map> myJoinMap;
+
PredicateBuilderDate(SearchBuilder theSearchBuilder) {
super(theSearchBuilder);
}
@@ -56,7 +60,18 @@ public class PredicateBuilderDate extends BasePredicateBuilder implements IPredi
List extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation operation) {
- Join join = createJoin(SearchBuilderJoinEnum.DATE, theParamName);
+ boolean newJoin = false;
+ if (myJoinMap == null) {
+ myJoinMap = new HashMap<>();
+ }
+ String key = theResourceName + " " + theParamName;
+
+ Join join = myJoinMap.get(key);
+ if (join == null) {
+ join = createJoin(SearchBuilderJoinEnum.DATE, theParamName);
+ myJoinMap.put(key, join);
+ newJoin = true;
+ }
if (theList.get(0).getMissing() != null) {
Boolean missing = theList.get(0).getMissing();
@@ -77,7 +92,14 @@ public class PredicateBuilderDate extends BasePredicateBuilder implements IPredi
}
Predicate orPredicates = myBuilder.or(toArray(codePredicates));
- myQueryRoot.addPredicate(orPredicates);
+
+ if (newJoin) {
+ Predicate identityAndValuePredicate = combineParamIndexPredicateWithParamNamePredicate(theResourceName, theParamName, join, orPredicates);
+ myQueryRoot.addPredicate(identityAndValuePredicate);
+ } else {
+ myQueryRoot.addPredicate(orPredicates);
+ }
+
return orPredicates;
}
@@ -86,12 +108,13 @@ public class PredicateBuilderDate extends BasePredicateBuilder implements IPredi
String theParamName,
CriteriaBuilder theBuilder,
From, ResourceIndexedSearchParamDate> theFrom) {
- return createPredicateDate(theParam,
+ Predicate predicateDate = createPredicateDate(theParam,
theResourceName,
theParamName,
theBuilder,
theFrom,
null);
+ return combineParamIndexPredicateWithParamNamePredicate(theResourceName, theParamName, theFrom, predicateDate);
}
private Predicate createPredicateDate(IQueryParameterType theParam,
@@ -99,7 +122,7 @@ public class PredicateBuilderDate extends BasePredicateBuilder implements IPredi
String theParamName,
CriteriaBuilder theBuilder,
From, ResourceIndexedSearchParamDate> theFrom,
- SearchFilterParser.CompareOperation operation) {
+ SearchFilterParser.CompareOperation theOperation) {
Predicate p;
if (theParam instanceof DateParam) {
@@ -109,7 +132,7 @@ public class PredicateBuilderDate extends BasePredicateBuilder implements IPredi
p = createPredicateDateFromRange(theBuilder,
theFrom,
range,
- operation);
+ theOperation);
} else {
// TODO: handle missing date param?
p = null;
@@ -119,12 +142,12 @@ public class PredicateBuilderDate extends BasePredicateBuilder implements IPredi
p = createPredicateDateFromRange(theBuilder,
theFrom,
range,
- operation);
+ theOperation);
} else {
throw new IllegalArgumentException("Invalid token type: " + theParam.getClass());
}
- return combineParamIndexPredicateWithParamNamePredicate(theResourceName, theParamName, theFrom, p);
+ return p;
}
private Predicate createPredicateDateFromRange(CriteriaBuilder theBuilder,
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderReference.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderReference.java
index 6077495a1c2..ca72f0a6f56 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderReference.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/predicate/PredicateBuilderReference.java
@@ -430,7 +430,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
break;
case Constants.PARAM_HAS:
- addPredicateHas(theAndOrParams, theRequest);
+ addPredicateHas(theResourceName, theAndOrParams, theRequest);
break;
case Constants.PARAM_TAG:
@@ -756,7 +756,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
return retVal;
}
- private void addPredicateHas(List> theHasParameters, RequestDetails theRequest) {
+ private void addPredicateHas(String theResourceType, List> theHasParameters, RequestDetails theRequest) {
for (List extends IQueryParameterType> nextOrList : theHasParameters) {
@@ -811,8 +811,9 @@ class PredicateBuilderReference extends BasePredicateBuilder {
Join join = myQueryRoot.join("myResourceLinksAsTarget", JoinType.LEFT);
Predicate pathPredicate = myPredicateBuilder.createResourceLinkPathPredicate(targetResourceType, paramReference, join);
- Predicate pidPredicate = join.get("mySourceResourcePid").in(subQ);
- Predicate andPredicate = myBuilder.and(pathPredicate, pidPredicate);
+ Predicate sourceTypePredicate = myBuilder.equal(join.get("myTargetResourceType"), theResourceType);
+ Predicate sourcePidPredicate = join.get("mySourceResourcePid").in(subQ);
+ Predicate andPredicate = myBuilder.and(pathPredicate, sourcePidPredicate, sourceTypePredicate);
myQueryRoot.addPredicate(andPredicate);
}
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoCodeSystemR5.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoCodeSystemR5.java
index 417db973235..94c9292757a 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoCodeSystemR5.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoCodeSystemR5.java
@@ -148,7 +148,7 @@ public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao
if (myDaoConfig.isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) {
if (retVal.getDeleted() == null) {
ValueSet valueSet = (ValueSet) theResource;
- myHapiTerminologySvc.storeTermValueSet(retVal, org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(valueSet));
+ myHapiTerminologySvc.storeTermValueSet(retVal, org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(valueSet));
} else {
myHapiTerminologySvc.deleteValueSetAndChildren(retVal);
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermCodeSystem.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermCodeSystem.java
index 73abe091453..ce89811024b 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermCodeSystem.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermCodeSystem.java
@@ -47,7 +47,7 @@ public class TermCodeSystem implements Serializable {
@Column(name = "CODE_SYSTEM_URI", nullable = false, length = MAX_URL_LENGTH)
private String myCodeSystemUri;
- @OneToOne()
+ @OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CURRENT_VERSION_PID", referencedColumnName = "PID", nullable = true, foreignKey = @ForeignKey(name = "FK_TRMCODESYSTEM_CURVER"))
private TermCodeSystemVersion myCurrentVersion;
@Column(name = "CURRENT_VERSION_PID", nullable = true, insertable = false, updatable = false)
@@ -57,7 +57,7 @@ public class TermCodeSystem implements Serializable {
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CODESYSTEM_PID")
@Column(name = "PID")
private Long myPid;
- @OneToOne()
+ @OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_TRMCODESYSTEM_RES"))
private ResourceTable myResource;
@Column(name = "RES_ID", insertable = false, updatable = false)
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermCodeSystemVersion.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermCodeSystemVersion.java
index f92e421888a..c87f76e3d3e 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermCodeSystemVersion.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermCodeSystemVersion.java
@@ -50,7 +50,7 @@ public class TermCodeSystemVersion implements Serializable {
@Column(name = "PID")
private Long myId;
- @OneToOne()
+ @OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_CODESYSVER_RES_ID"))
private ResourceTable myResource;
@@ -64,7 +64,7 @@ public class TermCodeSystemVersion implements Serializable {
* This was added in HAPI FHIR 3.3.0 and is nullable just to avoid migration
* issued. It should be made non-nullable at some point.
*/
- @ManyToOne
+ @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CODESYSTEM_PID", referencedColumnName = "PID", nullable = true, foreignKey = @ForeignKey(name = "FK_CODESYSVER_CS_ID"))
private TermCodeSystem myCodeSystem;
@@ -72,7 +72,7 @@ public class TermCodeSystemVersion implements Serializable {
private Long myCodeSystemPid;
@SuppressWarnings("unused")
- @OneToOne(mappedBy = "myCurrentVersion", optional = true)
+ @OneToOne(mappedBy = "myCurrentVersion", optional = true, fetch = FetchType.LAZY)
private TermCodeSystem myCodeSystemHavingThisVersionAsCurrentVersionIfAny;
@Column(name = "CS_DISPLAY", nullable = true, updatable = false, length = MAX_VERSION_LENGTH)
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java
index 1b6aa71b777..ab37618e3fa 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java
@@ -65,7 +65,7 @@ public class TermConcept implements Serializable {
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CONCEPT_UPDATED", nullable = true)
private Date myUpdated;
- @ManyToOne()
+ @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CODESYSTEM_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPT_PID_CS_PID"))
private TermCodeSystemVersion myCodeSystem;
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false)
@@ -79,11 +79,11 @@ public class TermConcept implements Serializable {
@Field(name = "myDisplayPhonetic", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "autocompletePhoneticAnalyzer"))
})
private String myDisplay;
- @OneToMany(mappedBy = "myConcept", orphanRemoval = false)
+ @OneToMany(mappedBy = "myConcept", orphanRemoval = false, fetch = FetchType.LAZY)
@Field(name = "PROPmyProperties", analyzer = @Analyzer(definition = "termConceptPropertyAnalyzer"))
@FieldBridge(impl = TermConceptPropertyFieldBridge.class)
private Collection myProperties;
- @OneToMany(mappedBy = "myConcept", orphanRemoval = false)
+ @OneToMany(mappedBy = "myConcept", orphanRemoval = false, fetch = FetchType.LAZY)
private Collection myDesignations;
@Id()
@SequenceGenerator(name = "SEQ_CONCEPT_PID", sequenceName = "SEQ_CONCEPT_PID")
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptDesignation.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptDesignation.java
index 58069ed8932..61cfcf80ee2 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptDesignation.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptDesignation.java
@@ -39,7 +39,7 @@ public class TermConceptDesignation implements Serializable {
public static final int MAX_LENGTH = 500;
public static final int MAX_VAL_LENGTH = 2000;
- @ManyToOne
+ @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CONCEPT_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTDESIG_CONCEPT"))
private TermConcept myConcept;
@Id()
@@ -62,7 +62,7 @@ public class TermConceptDesignation implements Serializable {
*
* @since 3.5.0
*/
- @ManyToOne
+ @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CS_VER_PID", nullable = true, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTDESIG_CSV"))
private TermCodeSystemVersion myCodeSystemVersion;
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptParentChildLink.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptParentChildLink.java
index a75511c57ab..2ceceabe931 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptParentChildLink.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptParentChildLink.java
@@ -32,14 +32,14 @@ import java.io.Serializable;
public class TermConceptParentChildLink implements Serializable {
private static final long serialVersionUID = 1L;
- @ManyToOne()
+ @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CHILD_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TERM_CONCEPTPC_CHILD"))
private TermConcept myChild;
@Column(name = "CHILD_PID", insertable = false, updatable = false)
private Long myChildPid;
- @ManyToOne()
+ @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CODESYSTEM_PID", nullable = false, foreignKey = @ForeignKey(name = "FK_TERM_CONCEPTPC_CS"))
private TermCodeSystemVersion myCodeSystem;
@@ -47,7 +47,7 @@ public class TermConceptParentChildLink implements Serializable {
@Fields({@Field(name = "myCodeSystemVersionPid")})
private long myCodeSystemVersionPid;
- @ManyToOne(cascade = {})
+ @ManyToOne(fetch = FetchType.LAZY, cascade = {})
@JoinColumn(name = "PARENT_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TERM_CONCEPTPC_PARENT"))
private TermConcept myParent;
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptProperty.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptProperty.java
index 7a59b5d3c3a..8bdbd909b24 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptProperty.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptProperty.java
@@ -44,7 +44,7 @@ public class TermConceptProperty implements Serializable {
private static final int MAX_LENGTH = 500;
static final int MAX_PROPTYPE_ENUM_LENGTH = 6;
- @ManyToOne
+ @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CONCEPT_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTPROP_CONCEPT"))
private TermConcept myConcept;
/**
@@ -52,7 +52,7 @@ public class TermConceptProperty implements Serializable {
*
* @since 3.5.0
*/
- @ManyToOne
+ @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CS_VER_PID", nullable = true, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTPROP_CSV"))
private TermCodeSystemVersion myCodeSystemVersion;
@Id()
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/TerminologyUploaderProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/TerminologyUploaderProvider.java
index d6ee3364a47..90a27e56c48 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/TerminologyUploaderProvider.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/TerminologyUploaderProvider.java
@@ -39,7 +39,6 @@ import ca.uhn.fhir.util.ValidateUtil;
import com.google.common.base.Charsets;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
-import org.hl7.fhir.convertors.VersionConvertor_30_40;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.ICompositeType;
@@ -61,6 +60,7 @@ import java.util.Map;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.trim;
+import static org.hl7.fhir.convertors.conv30_40.CodeSystem30_40.convertCodeSystem;
public class TerminologyUploaderProvider extends BaseJpaProvider {
@@ -272,10 +272,10 @@ public class TerminologyUploaderProvider extends BaseJpaProvider {
CodeSystem nextCodeSystem;
switch (getContext().getVersion().getVersion()) {
case DSTU3:
- nextCodeSystem = VersionConvertor_30_40.convertCodeSystem((org.hl7.fhir.dstu3.model.CodeSystem) theCodeSystem);
+ nextCodeSystem = convertCodeSystem((org.hl7.fhir.dstu3.model.CodeSystem) theCodeSystem);
break;
case R5:
- nextCodeSystem = org.hl7.fhir.convertors.conv40_50.CodeSystem.convertCodeSystem((org.hl7.fhir.r5.model.CodeSystem) theCodeSystem);
+ nextCodeSystem = org.hl7.fhir.convertors.conv40_50.CodeSystem40_50.convertCodeSystem((org.hl7.fhir.r5.model.CodeSystem) theCodeSystem);
break;
default:
nextCodeSystem = (CodeSystem) theCodeSystem;
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/BaseJpaResourceProviderConceptMapDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/BaseJpaResourceProviderConceptMapDstu3.java
index 7bcfee951a4..0f42082bbef 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/BaseJpaResourceProviderConceptMapDstu3.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/BaseJpaResourceProviderConceptMapDstu3.java
@@ -21,9 +21,9 @@ package ca.uhn.fhir.jpa.provider.dstu3;
*/
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap;
+import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.term.TranslationRequest;
import ca.uhn.fhir.jpa.term.TranslationResult;
-import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
@@ -31,11 +31,21 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import org.hl7.fhir.convertors.VersionConvertor_30_40;
-import org.hl7.fhir.dstu3.model.*;
+import org.hl7.fhir.dstu3.model.BooleanType;
+import org.hl7.fhir.dstu3.model.CodeType;
+import org.hl7.fhir.dstu3.model.CodeableConcept;
+import org.hl7.fhir.dstu3.model.Coding;
+import org.hl7.fhir.dstu3.model.ConceptMap;
+import org.hl7.fhir.dstu3.model.IdType;
+import org.hl7.fhir.dstu3.model.Parameters;
+import org.hl7.fhir.dstu3.model.StringType;
+import org.hl7.fhir.dstu3.model.UriType;
import org.hl7.fhir.exceptions.FHIRException;
import javax.servlet.http.HttpServletRequest;
+import static org.hl7.fhir.convertors.conv30_40.Parameters30_40.convertParameters;
+
public class BaseJpaResourceProviderConceptMapDstu3 extends JpaResourceProviderDstu3 {
@Operation(name = JpaConstants.OPERATION_TRANSLATE, idempotent = true, returnParameters = {
@OperationParam(name = "result", type = BooleanType.class, min = 1, max = 1),
@@ -129,7 +139,7 @@ public class BaseJpaResourceProviderConceptMapDstu3 extends JpaResourceProviderD
TranslationResult result = dao.translate(translationRequest, theRequestDetails);
// Convert from R4 to DSTU3
- return VersionConvertor_30_40.convertParameters(result.toParameters());
+ return convertParameters(result.toParameters());
} catch (FHIRException fe) {
throw new InternalErrorException(fe);
} finally {
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaResourceProviderDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaResourceProviderDstu3.java
index e6376d2ddf1..42aec253031 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaResourceProviderDstu3.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaResourceProviderDstu3.java
@@ -21,17 +21,28 @@ package ca.uhn.fhir.jpa.provider.dstu3;
*/
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
-import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
-import ca.uhn.fhir.rest.annotation.*;
+import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
+import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
+import ca.uhn.fhir.rest.annotation.Create;
+import ca.uhn.fhir.rest.annotation.Delete;
+import ca.uhn.fhir.rest.annotation.IdParam;
+import ca.uhn.fhir.rest.annotation.Operation;
+import ca.uhn.fhir.rest.annotation.OperationParam;
+import ca.uhn.fhir.rest.annotation.ResourceParam;
+import ca.uhn.fhir.rest.annotation.Update;
+import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
-import org.hl7.fhir.convertors.VersionConvertor_30_40;
-import org.hl7.fhir.dstu3.model.*;
+import org.hl7.fhir.dstu3.model.BooleanType;
+import org.hl7.fhir.dstu3.model.IdType;
+import org.hl7.fhir.dstu3.model.IntegerType;
+import org.hl7.fhir.dstu3.model.Meta;
+import org.hl7.fhir.dstu3.model.Parameters;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IIdType;
@@ -41,6 +52,7 @@ import javax.servlet.http.HttpServletRequest;
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META;
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_ADD;
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_DELETE;
+import static org.hl7.fhir.convertors.conv30_40.Parameters30_40.convertParameters;
public class JpaResourceProviderDstu3 extends BaseJpaResourceProvider {
@@ -91,7 +103,7 @@ public class JpaResourceProviderDstu3 extends BaseJpaRes
RequestDetails theRequest) {
org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(theIdParam, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null, theRequest);
try {
- return VersionConvertor_30_40.convertParameters(retVal);
+ return convertParameters(retVal);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -107,7 +119,7 @@ public class JpaResourceProviderDstu3 extends BaseJpaRes
RequestDetails theRequest) {
org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(null, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null, theRequest);
try {
- return VersionConvertor_30_40.convertParameters(retVal);
+ return convertParameters(retVal);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaSystemProviderDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaSystemProviderDstu3.java
index f345c6f7361..c1f1970a0c1 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaSystemProviderDstu3.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaSystemProviderDstu3.java
@@ -3,17 +3,26 @@ package ca.uhn.fhir.jpa.provider.dstu3;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl.Suggestion;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
-import ca.uhn.fhir.jpa.provider.BaseJpaSystemProviderDstu2Plus;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
+import ca.uhn.fhir.jpa.provider.BaseJpaSystemProviderDstu2Plus;
import ca.uhn.fhir.model.api.annotation.Description;
-import ca.uhn.fhir.rest.annotation.*;
+import ca.uhn.fhir.rest.annotation.IdParam;
+import ca.uhn.fhir.rest.annotation.Operation;
+import ca.uhn.fhir.rest.annotation.OperationParam;
+import ca.uhn.fhir.rest.annotation.Transaction;
+import ca.uhn.fhir.rest.annotation.TransactionParam;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
-import org.hl7.fhir.convertors.VersionConvertor_30_40;
-import org.hl7.fhir.dstu3.model.*;
+import org.hl7.fhir.dstu3.model.BooleanType;
+import org.hl7.fhir.dstu3.model.Bundle;
+import org.hl7.fhir.dstu3.model.DecimalType;
+import org.hl7.fhir.dstu3.model.IntegerType;
+import org.hl7.fhir.dstu3.model.Meta;
+import org.hl7.fhir.dstu3.model.Parameters;
import org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent;
+import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IIdType;
@@ -29,6 +38,7 @@ import java.util.TreeMap;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import static org.apache.commons.lang3.StringUtils.isBlank;
+import static org.hl7.fhir.convertors.conv30_40.Parameters30_40.convertParameters;
/*
* #%L
@@ -72,7 +82,7 @@ public class JpaSystemProviderDstu3 extends BaseJpaSystemProviderDstu2Plus dao = (IFhirResourceDaoConceptMap) getDao();
TranslationResult result = dao.translate(translationRequest, theRequestDetails);
org.hl7.fhir.r4.model.Parameters parameters = result.toParameters();
- return org.hl7.fhir.convertors.conv40_50.Parameters.convertParameters(parameters);
+ return org.hl7.fhir.convertors.conv40_50.Parameters40_50.convertParameters(parameters);
} finally {
endRequest(theServletRequest);
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/JpaResourceProviderR5.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/JpaResourceProviderR5.java
index e3e4c6b54de..ef86e4f478b 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/JpaResourceProviderR5.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/JpaResourceProviderR5.java
@@ -86,7 +86,7 @@ public class JpaResourceProviderR5 extends BaseJpaResour
RequestDetails theRequest) {
org.hl7.fhir.r4.model.Parameters parameters = super.doExpunge(theIdParam, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null, theRequest);
- return org.hl7.fhir.convertors.conv40_50.Parameters.convertParameters(parameters);
+ return org.hl7.fhir.convertors.conv40_50.Parameters40_50.convertParameters(parameters);
}
@@ -99,7 +99,7 @@ public class JpaResourceProviderR5 extends BaseJpaResour
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) BooleanType theExpungeOldVersions,
RequestDetails theRequest) {
org.hl7.fhir.r4.model.Parameters parameters = super.doExpunge(null, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null, theRequest);
- return org.hl7.fhir.convertors.conv40_50.Parameters.convertParameters(parameters);
+ return org.hl7.fhir.convertors.conv40_50.Parameters40_50.convertParameters(parameters);
}
@Operation(name = OPERATION_META, idempotent = true, returnParameters = {
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/JpaSystemProviderR5.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/JpaSystemProviderR5.java
index 7bacb42b6ba..4a99a931bbe 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/JpaSystemProviderR5.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/JpaSystemProviderR5.java
@@ -68,7 +68,7 @@ public class JpaSystemProviderR5 extends BaseJpaSystemProviderDstu2Plus doHistoryInTransaction(theFromIndex, theToIndex));
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java
index 731f4019148..7125a415277 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java
@@ -56,6 +56,9 @@ import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.rest.server.util.ICachedSearchDetails;
import ca.uhn.fhir.util.AsyncUtil;
import ca.uhn.fhir.util.StopWatch;
+import co.elastic.apm.api.ElasticApm;
+import co.elastic.apm.api.Span;
+import co.elastic.apm.api.Transaction;
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.exception.ExceptionUtils;
@@ -601,7 +604,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
private List myPreviouslyAddedResourcePids;
private Integer myMaxResultsToFetch;
private SearchRuntimeDetails mySearchRuntimeDetails;
-
+ private Transaction myParentTransaction;
/**
* Constructor
*/
@@ -614,6 +617,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
mySearchRuntimeDetails = new SearchRuntimeDetails(theRequest, mySearch.getUuid());
mySearchRuntimeDetails.setQueryString(theParams.toNormalizedQueryString(theCallingDao.getContext()));
myRequest = theRequest;
+ myParentTransaction = ElasticApm.currentTransaction();
}
/**
@@ -774,10 +778,11 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
if (theResultIter.hasNext() == false) {
int skippedCount = theResultIter.getSkippedCount();
+ int nonSkippedCount = theResultIter.getNonSkippedCount();
int totalFetched = skippedCount + myCountSavedThisPass + myCountBlockedThisPass;
ourLog.trace("MaxToFetch[{}] SkippedCount[{}] CountSavedThisPass[{}] CountSavedThisTotal[{}] AdditionalPrefetchRemaining[{}]", myMaxResultsToFetch, skippedCount, myCountSavedThisPass, myCountSavedTotal, myAdditionalPrefetchThresholdsRemaining);
- if (myMaxResultsToFetch != null && totalFetched < myMaxResultsToFetch) {
+ if (nonSkippedCount == 0 || (myMaxResultsToFetch != null && totalFetched < myMaxResultsToFetch)) {
ourLog.trace("Setting search status to FINISHED");
mySearch.setStatus(SearchStatusEnum.FINISHED);
mySearch.setTotalCount(myCountSavedTotal);
@@ -840,7 +845,8 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
@Override
public Void call() {
StopWatch sw = new StopWatch();
-
+ Span span = myParentTransaction.startSpan("db", "query", "search");
+ span.setName("FHIR Database Search");
try {
// Create an initial search in the DB and give it an ID
saveSearch();
@@ -896,7 +902,6 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
ourLog.error("Failed during search loading after {}ms", sw.getMillis(), t);
}
myUnsyncedPids.clear();
-
Throwable rootCause = ExceptionUtils.getRootCause(t);
rootCause = defaultIfNull(rootCause, t);
@@ -923,12 +928,13 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, myRequest, Pointcut.JPA_PERFTRACE_SEARCH_FAILED, params);
saveSearch();
-
+ span.captureException(t);
} finally {
myIdToSearchTask.remove(mySearch.getUuid());
myInitialCollectionLatch.countDown();
markComplete();
+ span.end();
}
return null;
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java
index 02891e7c508..f8175bf481e 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java
@@ -66,6 +66,7 @@ import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.MultiPhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RegexpQuery;
+import org.apache.lucene.search.TermQuery;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.search.jpa.FullTextEntityManager;
@@ -600,11 +601,16 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc, ApplicationCo
.map(t -> new Term("myCode", t))
.collect(Collectors.toList());
if (codes.size() > 0) {
- MultiPhraseQuery query = new MultiPhraseQuery();
- query.add(codes.toArray(new Term[0]));
+
+ BooleanQuery.Builder builder = new BooleanQuery.Builder();
+ builder.setMinimumNumberShouldMatch(1);
+ for (Term nextCode : codes) {
+ builder.add(new TermQuery(nextCode), BooleanClause.Occur.SHOULD);
+ }
+
luceneQuery = new BooleanQuery.Builder()
.add(luceneQuery, BooleanClause.Occur.MUST)
- .add(query, BooleanClause.Occur.MUST)
+ .add(builder.build(), BooleanClause.Occur.MUST)
.build();
}
@@ -1240,6 +1246,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc, ApplicationCo
return retVal;
}
+ @Transactional
@Override
public List findCodesAbove(String theSystem, String theCode) {
TermCodeSystem cs = getCodeSystem(theSystem);
@@ -1271,6 +1278,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc, ApplicationCo
return retVal;
}
+ @Transactional
@Override
public List findCodesBelow(String theSystem, String theCode) {
TermCodeSystem cs = getCodeSystem(theSystem);
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermCodeSystemStorageSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermCodeSystemStorageSvcImpl.java
index 43648e3e99c..da22a1f823b 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermCodeSystemStorageSvcImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermCodeSystemStorageSvcImpl.java
@@ -45,7 +45,6 @@ import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
-import ca.uhn.fhir.jpa.util.ScrollableResultsIterator;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
@@ -53,11 +52,7 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.ObjectUtil;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.ValidateUtil;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ListMultimap;
import org.apache.commons.lang3.Validate;
-import org.hibernate.ScrollMode;
-import org.hibernate.ScrollableResults;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.ConceptMap;
@@ -78,11 +73,6 @@ import javax.annotation.Nonnull;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
-import javax.persistence.TypedQuery;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -165,11 +155,12 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
IIdType codeSystemId = cs.getResource().getIdDt();
UploadStatistics retVal = new UploadStatistics(codeSystemId);
+ HashMap codeToConcept = new HashMap<>();
// Add root concepts
for (TermConcept nextRootConcept : theAdditions.getRootConcepts()) {
List parentCodes = Collections.emptyList();
- addConcept(csv, parentCodes, nextRootConcept, retVal, true, 0);
+ addConceptInHierarchy(csv, parentCodes, nextRootConcept, retVal, codeToConcept, 0);
}
return retVal;
@@ -232,7 +223,15 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
* save parent concepts first (it's way too slow to do that)
*/
if (theConcept.getId() == null) {
- retVal += ensureParentsSaved(theConcept.getParents());
+ boolean needToSaveParents = false;
+ for (TermConceptParentChildLink next : theConcept.getParents()) {
+ if (next.getParent().getId() == null) {
+ needToSaveParents = true;
+ }
+ }
+ if (needToSaveParents) {
+ retVal += ensureParentsSaved(theConcept.getParents());
+ }
}
if (theConcept.getId() == null || theConcept.getIndexStatus() == null) {
@@ -445,66 +444,68 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
Validate.isTrue(myContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3), "Terminology operations only supported in DSTU3+ mode");
}
- private void addConcept(TermCodeSystemVersion theCsv, Collection theParentCodes, TermConcept theConceptToAdd, UploadStatistics theStatisticsTracker, boolean theRootConcept, int theSequence) {
+ private void addConceptInHierarchy(TermCodeSystemVersion theCsv, Collection theParentCodes, TermConcept theConceptToAdd, UploadStatistics theStatisticsTracker, Map theCodeToConcept, int theSequence) {
TermConcept conceptToAdd = theConceptToAdd;
List childrenToAdd = theConceptToAdd.getChildren();
String nextCodeToAdd = conceptToAdd.getCode();
String parentDescription = "(root concept)";
- Set parentConcepts = new HashSet<>();
-
- if (!theParentCodes.isEmpty()) {
- parentDescription = "[" + String.join(", ", theParentCodes) + "]";
- for (String nextParentCode : theParentCodes) {
- Optional nextParentOpt = myConceptDao.findByCodeSystemAndCode(theCsv, nextParentCode);
- if (nextParentOpt.isPresent() == false) {
- throw new InvalidRequestException("Unable to add code \"" + nextCodeToAdd + "\" to unknown parent: " + nextParentCode);
- }
- parentConcepts.add(nextParentOpt.get());
- }
- }
ourLog.info("Saving concept {} with parent {}", theStatisticsTracker.getUpdatedConceptCount(), parentDescription);
Optional existingCodeOpt = myConceptDao.findByCodeSystemAndCode(theCsv, nextCodeToAdd);
+ List existingParentLinks;
if (existingCodeOpt.isPresent()) {
TermConcept existingCode = existingCodeOpt.get();
existingCode.setIndexStatus(null);
existingCode.setDisplay(conceptToAdd.getDisplay());
conceptToAdd = existingCode;
+ existingParentLinks = conceptToAdd.getParents();
+ } else {
+ existingParentLinks = Collections.emptyList();
+ }
+
+ Set parentConceptsWeShouldLinkTo = new HashSet<>();
+ for (String nextParentCode : theParentCodes) {
+
+ // Don't add parent links that already exist for the code
+ if (existingParentLinks.stream().anyMatch(t -> t.getParent().getCode().equals(nextParentCode))) {
+ continue;
+ }
+
+ TermConcept nextParentOpt = theCodeToConcept.get(nextParentCode);
+ if (nextParentOpt == null) {
+ nextParentOpt = myConceptDao.findByCodeSystemAndCode(theCsv, nextParentCode).orElse(null);
+ }
+ if (nextParentOpt == null) {
+ throw new InvalidRequestException("Unable to add code \"" + nextCodeToAdd + "\" to unknown parent: " + nextParentCode);
+ }
+ parentConceptsWeShouldLinkTo.add(nextParentOpt);
}
if (conceptToAdd.getSequence() == null) {
conceptToAdd.setSequence(theSequence);
}
- // Drop any old parent-child links if they aren't explicitly specified in the
- // hierarchy being added
- if (!theRootConcept) {
- for (Iterator iter = conceptToAdd.getParents().iterator(); iter.hasNext(); ) {
- TermConceptParentChildLink nextLink = iter.next();
- String parentCode = nextLink.getParent().getCode();
- ourLog.info("Dropping existing parent/child link from {} -> {}", parentCode, nextCodeToAdd);
- myConceptParentChildLinkDao.delete(nextLink);
- iter.remove();
-
- List parentChildrenList = nextLink.getParent().getChildren();
- parentChildrenList.remove(nextLink);
- }
- }
-
// Null out the hierarchy PIDs for this concept always. We do this because we're going to
// force a reindex, and it'll be regenerated then
conceptToAdd.setParentPids(null);
conceptToAdd.setCodeSystemVersion(theCsv);
- conceptToAdd = myConceptDao.save(conceptToAdd);
- Long nextConceptPid = conceptToAdd.getId();
- Validate.notNull(nextConceptPid);
+ if (theStatisticsTracker.getUpdatedConceptCount() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) {
+ saveConcept(conceptToAdd);
+ Long nextConceptPid = conceptToAdd.getId();
+ Validate.notNull(nextConceptPid);
+ } else {
+ myDeferredStorageSvc.addConceptToStorageQueue(conceptToAdd);
+ }
+
+ theCodeToConcept.put(conceptToAdd.getCode(), conceptToAdd);
+
theStatisticsTracker.incrementUpdatedConceptCount();
// Add link to new child to the parent
- for (TermConcept nextParentConcept : parentConcepts) {
+ for (TermConcept nextParentConcept : parentConceptsWeShouldLinkTo) {
TermConceptParentChildLink parentLink = new TermConceptParentChildLink();
parentLink.setParent(nextParentConcept);
parentLink.setChild(conceptToAdd);
@@ -513,7 +514,13 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
nextParentConcept.getChildren().add(parentLink);
conceptToAdd.getParents().add(parentLink);
ourLog.info("Saving parent/child link - Parent[{}] Child[{}]", parentLink.getParent().getCode(), parentLink.getChild().getCode());
- myConceptParentChildLinkDao.save(parentLink);
+
+ if (theStatisticsTracker.getUpdatedConceptCount() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) {
+ myConceptParentChildLinkDao.save(parentLink);
+ } else {
+ myDeferredStorageSvc.addConceptLinkToStorageQueue(parentLink);
+ }
+
}
ourLog.trace("About to save parent-child links");
@@ -527,13 +534,20 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
for (int i = 0; i < nextChild.getParents().size(); i++) {
if (nextChild.getParents().get(i).getId() == null) {
String parentCode = nextChild.getParents().get(i).getParent().getCode();
- TermConcept parentConcept = myConceptDao.findByCodeSystemAndCode(theCsv, parentCode).orElseThrow(() -> new IllegalArgumentException("Unknown parent code: " + parentCode));
+ TermConcept parentConcept = theCodeToConcept.get(parentCode);
+ if (parentConcept == null) {
+ parentConcept = myConceptDao.findByCodeSystemAndCode(theCsv, parentCode).orElse(null);
+ }
+ if (parentConcept == null) {
+ throw new IllegalArgumentException("Unknown parent code: " + parentCode);
+ }
+
nextChild.getParents().get(i).setParent(parentConcept);
}
}
Collection parentCodes = nextChild.getParents().stream().map(t -> t.getParent().getCode()).collect(Collectors.toList());
- addConcept(theCsv, parentCodes, nextChild, theStatisticsTracker, false, childIndex);
+ addConceptInHierarchy(theCsv, parentCodes, nextChild, theStatisticsTracker, theCodeToConcept, childIndex);
childIndex++;
}
@@ -649,12 +663,15 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
private void deleteConceptChildrenAndConcept(TermConcept theConcept, AtomicInteger theRemoveCounter) {
for (TermConceptParentChildLink nextChildLink : theConcept.getChildren()) {
deleteConceptChildrenAndConcept(nextChildLink.getChild(), theRemoveCounter);
- myConceptParentChildLinkDao.delete(nextChildLink);
}
+ myConceptParentChildLinkDao.deleteByConceptPid(theConcept.getId());
+
myConceptDesignationDao.deleteAll(theConcept.getDesignations());
myConceptPropertyDao.deleteAll(theConcept.getProperties());
- myConceptDao.delete(theConcept);
+
+ ourLog.info("Deleting concept {} - Code {}", theConcept.getId(), theConcept.getCode());
+ myConceptDao.deleteByPid(theConcept.getId());
theRemoveCounter.incrementAndGet();
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermDeferredStorageSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermDeferredStorageSvcImpl.java
index e262ef1cedb..09e7cc7e69b 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermDeferredStorageSvcImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermDeferredStorageSvcImpl.java
@@ -98,6 +98,13 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
myDeferredValueSets.addAll(theValueSets);
}
+ @Override
+ public void saveAllDeferred() {
+ while (!isStorageQueueEmpty()) {
+ saveDeferred();
+ }
+ }
+
@Override
public void setProcessDeferred(boolean theProcessDeferred) {
myProcessDeferred = theProcessDeferred;
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcDstu3.java
index 6f949a61933..aee82c3ce8c 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcDstu3.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcDstu3.java
@@ -9,10 +9,13 @@ import ca.uhn.fhir.jpa.term.api.ITermReadSvcDstu3;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.CoverageIgnore;
import ca.uhn.fhir.util.ValidateUtil;
-import org.hl7.fhir.convertors.VersionConvertor_30_40;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
-import org.hl7.fhir.dstu3.model.*;
+import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
+import org.hl7.fhir.dstu3.model.CodeableConcept;
+import org.hl7.fhir.dstu3.model.Coding;
+import org.hl7.fhir.dstu3.model.StructureDefinition;
+import org.hl7.fhir.dstu3.model.ValueSet;
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent;
import org.hl7.fhir.exceptions.FHIRException;
@@ -31,6 +34,9 @@ import java.util.List;
import java.util.Optional;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
+import static org.hl7.fhir.convertors.conv30_40.CodeSystem30_40.convertCodeSystem;
+import static org.hl7.fhir.convertors.conv30_40.ValueSet30_40.convertValueSet;
+import static org.hl7.fhir.convertors.conv30_40.ValueSet30_40.convertValueSetExpansionComponent;
/*
* #%L
@@ -104,7 +110,7 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
org.hl7.fhir.r4.model.ValueSet valueSetToExpandR4;
valueSetToExpandR4 = toCanonicalValueSet(valueSetToExpand);
org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionComponent expandedR4 = super.expandValueSetInMemory(valueSetToExpandR4, null).getExpansion();
- return VersionConvertor_30_40.convertValueSetExpansionComponent(expandedR4);
+ return convertValueSetExpansionComponent(expandedR4);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -118,7 +124,7 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
org.hl7.fhir.r4.model.ValueSet valueSetToExpandR4;
valueSetToExpandR4 = toCanonicalValueSet(valueSetToExpand);
org.hl7.fhir.r4.model.ValueSet expandedR4 = super.expandValueSetInMemory(valueSetToExpandR4, null);
- return VersionConvertor_30_40.convertValueSet(expandedR4);
+ return convertValueSet(expandedR4);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -127,7 +133,7 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
@Override
protected org.hl7.fhir.r4.model.ValueSet toCanonicalValueSet(IBaseResource theValueSet) throws FHIRException {
org.hl7.fhir.r4.model.ValueSet valueSetToExpandR4;
- valueSetToExpandR4 = VersionConvertor_30_40.convertValueSet((ValueSet) theValueSet);
+ valueSetToExpandR4 = convertValueSet((ValueSet) theValueSet);
return valueSetToExpandR4;
}
@@ -139,7 +145,7 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
org.hl7.fhir.r4.model.ValueSet valueSetToExpandR4;
valueSetToExpandR4 = toCanonicalValueSet(valueSetToExpand);
org.hl7.fhir.r4.model.ValueSet expandedR4 = super.expandValueSet(valueSetToExpandR4, theOffset, theCount);
- return VersionConvertor_30_40.convertValueSet(expandedR4);
+ return convertValueSet(expandedR4);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -256,7 +262,7 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
public org.hl7.fhir.r4.model.CodeSystem getCodeSystemFromContext(String theSystem) {
CodeSystem codeSystem = myValidationSupport.fetchCodeSystem(myContext, theSystem);
try {
- return VersionConvertor_30_40.convertCodeSystem(codeSystem);
+ return convertCodeSystem(codeSystem);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -323,7 +329,7 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
public ValidateCodeResult validateCodeIsInPreExpandedValueSet(IBaseResource theValueSet, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept) {
ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSet, "ValueSet must not be null");
ValueSet valueSet = (ValueSet) theValueSet;
- org.hl7.fhir.r4.model.ValueSet valueSetR4 = VersionConvertor_30_40.convertValueSet(valueSet);
+ org.hl7.fhir.r4.model.ValueSet valueSetR4 = convertValueSet(valueSet);
Coding coding = (Coding) theCoding;
org.hl7.fhir.r4.model.Coding codingR4 = null;
@@ -347,7 +353,7 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
public boolean isValueSetPreExpandedForCodeValidation(IBaseResource theValueSet) {
ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSet, "ValueSet must not be null");
ValueSet valueSet = (ValueSet) theValueSet;
- org.hl7.fhir.r4.model.ValueSet valueSetR4 = VersionConvertor_30_40.convertValueSet(valueSet);
+ org.hl7.fhir.r4.model.ValueSet valueSetR4 = convertValueSet(valueSet);
return super.isValueSetPreExpandedForCodeValidation(valueSetR4);
}
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcR5.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcR5.java
index 6449945ddb2..a4f8ab5136b 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcR5.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcR5.java
@@ -90,21 +90,21 @@ public class TermReadSvcR5 extends BaseTermReadSvcImpl implements IValidationSup
super.throwInvalidValueSet(theValueSet);
}
- return expandValueSetAndReturnVersionIndependentConcepts(org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(valueSetR5), null);
+ return expandValueSetAndReturnVersionIndependentConcepts(org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(valueSetR5), null);
}
@Override
public IBaseResource expandValueSet(IBaseResource theInput) {
org.hl7.fhir.r4.model.ValueSet valueSetToExpand = toCanonicalValueSet(theInput);
org.hl7.fhir.r4.model.ValueSet valueSetR4 = super.expandValueSetInMemory(valueSetToExpand, null);
- return org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(valueSetR4);
+ return org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(valueSetR4);
}
@Override
public IBaseResource expandValueSet(IBaseResource theInput, int theOffset, int theCount) {
org.hl7.fhir.r4.model.ValueSet valueSetToExpand = toCanonicalValueSet(theInput);
org.hl7.fhir.r4.model.ValueSet valueSetR4 = super.expandValueSet(valueSetToExpand, theOffset, theCount);
- return org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(valueSetR4);
+ return org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(valueSetR4);
}
@Override
@@ -117,8 +117,8 @@ public class TermReadSvcR5 extends BaseTermReadSvcImpl implements IValidationSup
public ValueSetExpander.ValueSetExpansionOutcome expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) {
ValueSet valueSetToExpand = new ValueSet();
valueSetToExpand.getCompose().addInclude(theInclude);
- org.hl7.fhir.r4.model.ValueSet expandedR4 = super.expandValueSetInMemory(org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(valueSetToExpand), null);
- return new ValueSetExpander.ValueSetExpansionOutcome(org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(expandedR4));
+ org.hl7.fhir.r4.model.ValueSet expandedR4 = super.expandValueSetInMemory(org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(valueSetToExpand), null);
+ return new ValueSetExpander.ValueSetExpansionOutcome(org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(expandedR4));
}
@Override
@@ -199,13 +199,13 @@ public class TermReadSvcR5 extends BaseTermReadSvcImpl implements IValidationSup
@Override
public org.hl7.fhir.r4.model.CodeSystem getCodeSystemFromContext(String theSystem) {
CodeSystem codeSystemR5 = myValidationSupport.fetchCodeSystem(myContext, theSystem);
- return org.hl7.fhir.convertors.conv40_50.CodeSystem.convertCodeSystem(codeSystemR5);
+ return org.hl7.fhir.convertors.conv40_50.CodeSystem40_50.convertCodeSystem(codeSystemR5);
}
@Override
protected org.hl7.fhir.r4.model.ValueSet getValueSetFromResourceTable(ResourceTable theResourceTable) {
ValueSet valueSetR5 = myValueSetResourceDao.toResource(ValueSet.class, theResourceTable, null, false);
- return org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(valueSetR5);
+ return org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(valueSetR5);
}
@Override
@@ -277,7 +277,7 @@ public class TermReadSvcR5 extends BaseTermReadSvcImpl implements IValidationSup
@Override
protected org.hl7.fhir.r4.model.ValueSet toCanonicalValueSet(IBaseResource theValueSet) throws org.hl7.fhir.exceptions.FHIRException {
- return org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet((ValueSet) theValueSet);
+ return org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet((ValueSet) theValueSet);
}
@Override
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermVersionAdapterSvcDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermVersionAdapterSvcDstu3.java
index 925d0503811..5fce60cfa30 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermVersionAdapterSvcDstu3.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermVersionAdapterSvcDstu3.java
@@ -37,6 +37,9 @@ import org.springframework.context.event.ContextStartedEvent;
import org.springframework.context.event.EventListener;
import static org.apache.commons.lang3.StringUtils.isBlank;
+import static org.hl7.fhir.convertors.conv30_40.CodeSystem30_40.convertCodeSystem;
+import static org.hl7.fhir.convertors.conv30_40.ConceptMap30_40.convertConceptMap;
+import static org.hl7.fhir.convertors.conv30_40.ValueSet30_40.convertValueSet;
public class TermVersionAdapterSvcDstu3 extends BaseTermVersionAdapterSvcImpl implements ITermVersionAdapterSvc {
@@ -72,7 +75,7 @@ public class TermVersionAdapterSvcDstu3 extends BaseTermVersionAdapterSvcImpl im
public IIdType createOrUpdateCodeSystem(org.hl7.fhir.r4.model.CodeSystem theCodeSystemResource) {
CodeSystem resourceToStore;
try {
- resourceToStore = VersionConvertor_30_40.convertCodeSystem(theCodeSystemResource);
+ resourceToStore = convertCodeSystem(theCodeSystemResource);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -89,7 +92,7 @@ public class TermVersionAdapterSvcDstu3 extends BaseTermVersionAdapterSvcImpl im
public void createOrUpdateConceptMap(org.hl7.fhir.r4.model.ConceptMap theConceptMap) {
ConceptMap resourceToStore;
try {
- resourceToStore = VersionConvertor_30_40.convertConceptMap(theConceptMap);
+ resourceToStore = convertConceptMap(theConceptMap);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -105,7 +108,7 @@ public class TermVersionAdapterSvcDstu3 extends BaseTermVersionAdapterSvcImpl im
public void createOrUpdateValueSet(org.hl7.fhir.r4.model.ValueSet theValueSet) {
ValueSet valueSetDstu3;
try {
- valueSetDstu3 = VersionConvertor_30_40.convertValueSet(theValueSet);
+ valueSetDstu3 = convertValueSet(theValueSet);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermVersionAdapterSvcR5.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermVersionAdapterSvcR5.java
index f0f653d3667..83cc9c0ae76 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermVersionAdapterSvcR5.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermVersionAdapterSvcR5.java
@@ -62,7 +62,7 @@ public class TermVersionAdapterSvcR5 extends BaseTermVersionAdapterSvcImpl imple
public IIdType createOrUpdateCodeSystem(org.hl7.fhir.r4.model.CodeSystem theCodeSystemResource) {
validateCodeSystemForStorage(theCodeSystemResource);
- CodeSystem codeSystemR4 = org.hl7.fhir.convertors.conv40_50.CodeSystem.convertCodeSystem(theCodeSystemResource);
+ CodeSystem codeSystemR4 = org.hl7.fhir.convertors.conv40_50.CodeSystem40_50.convertCodeSystem(theCodeSystemResource);
if (isBlank(theCodeSystemResource.getIdElement().getIdPart())) {
String matchUrl = "CodeSystem?url=" + UrlUtil.escapeUrlParam(theCodeSystemResource.getUrl());
return myCodeSystemResourceDao.update(codeSystemR4, matchUrl).getId();
@@ -74,7 +74,7 @@ public class TermVersionAdapterSvcR5 extends BaseTermVersionAdapterSvcImpl imple
@Override
public void createOrUpdateConceptMap(org.hl7.fhir.r4.model.ConceptMap theConceptMap) {
- ConceptMap conceptMapR4 = org.hl7.fhir.convertors.conv40_50.ConceptMap.convertConceptMap(theConceptMap);
+ ConceptMap conceptMapR4 = org.hl7.fhir.convertors.conv40_50.ConceptMap40_50.convertConceptMap(theConceptMap);
if (isBlank(theConceptMap.getIdElement().getIdPart())) {
String matchUrl = "ConceptMap?url=" + UrlUtil.escapeUrlParam(theConceptMap.getUrl());
@@ -87,7 +87,7 @@ public class TermVersionAdapterSvcR5 extends BaseTermVersionAdapterSvcImpl imple
@Override
public void createOrUpdateValueSet(org.hl7.fhir.r4.model.ValueSet theValueSet) {
- ValueSet valueSetR4 = org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(theValueSet);
+ ValueSet valueSetR4 = org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(theValueSet);
if (isBlank(theValueSet.getIdElement().getIdPart())) {
String matchUrl = "ValueSet?url=" + UrlUtil.escapeUrlParam(theValueSet.getUrl());
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/api/ITermDeferredStorageSvc.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/api/ITermDeferredStorageSvc.java
index 881ce14e7f6..2aff45f7fef 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/api/ITermDeferredStorageSvc.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/api/ITermDeferredStorageSvc.java
@@ -50,4 +50,9 @@ public interface ITermDeferredStorageSvc {
void addConceptMapsToStorageQueue(List theConceptMaps);
void addValueSetsToStorageQueue(List theValueSets);
+
+ /**
+ * This is mostly here for unit tests - Saves any and all deferred concepts and links
+ */
+ void saveAllDeferred();
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/SearchBuilderTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/SearchBuilderTest.java
index fcefe28b6cf..9915a2cddb0 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/SearchBuilderTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/SearchBuilderTest.java
@@ -39,11 +39,10 @@ public class SearchBuilderTest {
TypedQuery mockQuery = mock(TypedQuery.class);
when(mockEntityManager.createQuery(any(), any())).thenReturn(mockQuery);
- List resultList = new ArrayList<>();
- ResourceLink link = new ResourceLink();
+ List resultList = new ArrayList<>();
+ Long link = 1L;
ResourceTable target = new ResourceTable();
target.setId(1L);
- link.setTargetResource(target);
resultList.add(link);
when(mockQuery.getResultList()).thenReturn(resultList);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2ValidateTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2ValidateTest.java
index df32f31e341..f02a9203011 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2ValidateTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2ValidateTest.java
@@ -1,9 +1,5 @@
package ca.uhn.fhir.jpa.dao.dstu2;
-import static org.hamcrest.Matchers.containsString;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
@@ -32,7 +28,11 @@ import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
-import java.util.Arrays;
+import java.util.Collections;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2ValidateTest.class);
@@ -94,15 +94,14 @@ public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
myStructureDefinitionDao.create(sd, mySrd);
Observation input = new Observation();
- ResourceMetadataKeyEnum.PROFILES.put(input, Arrays.asList(new IdDt(sd.getUrl())));
+ ResourceMetadataKeyEnum.PROFILES.put(input, Collections.singletonList(new IdDt(sd.getUrl())));
input.addIdentifier().setSystem("http://acme").setValue("12345");
input.getEncounter().setReference("http://foo.com/Encounter/9");
input.setStatus(ObservationStatusEnum.FINAL);
input.getCode().addCoding().setSystem("http://loinc.org").setCode("12345");
- String encoded = null;
- MethodOutcome outcome = null;
+ String encoded;
ValidationModeEnum mode = ValidationModeEnum.CREATE;
switch (enc) {
case JSON:
@@ -130,12 +129,12 @@ public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
}
@Test
- public void testValidateResourceContainingProfileDeclarationInvalid() throws Exception {
+ public void testValidateResourceContainingProfileDeclarationInvalid() {
String methodName = "testValidateResourceContainingProfileDeclarationInvalid";
Observation input = new Observation();
String profileUri = "http://example.com/StructureDefinition/" + methodName;
- ResourceMetadataKeyEnum.PROFILES.put(input, Arrays.asList(new IdDt(profileUri)));
+ ResourceMetadataKeyEnum.PROFILES.put(input, Collections.singletonList(new IdDt(profileUri)));
input.addIdentifier().setSystem("http://acme").setValue("12345");
input.getEncounter().setReference("http://foo.com/Encounter/9");
@@ -148,7 +147,7 @@ public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
String ooString = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome.getOperationOutcome());
ourLog.info(ooString);
- assertThat(ooString, containsString("StructureDefinition reference \\\"" + profileUri + "\\\" could not be resolved"));
+ assertThat(ooString, containsString("Profile reference 'http://example.com/StructureDefinition/testValidateResourceContainingProfileDeclarationInvalid' could not be resolved, so has not been checked"));
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java
index 45bb5e84837..bdc3ad3a2d7 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java
@@ -35,7 +35,6 @@ import ca.uhn.fhir.util.UrlUtil;
import org.apache.commons.io.IOUtils;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.Search;
-import org.hl7.fhir.convertors.VersionConvertor_30_40;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.exceptions.FHIRException;
@@ -60,6 +59,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
+import static org.hl7.fhir.convertors.conv30_40.ConceptMap30_40.convertConceptMap;
import static org.junit.Assert.fail;
@RunWith(SpringJUnit4ClassRunner.class)
@@ -386,7 +386,7 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
*/
public static ConceptMap createConceptMap() {
try {
- return VersionConvertor_30_40.convertConceptMap(BaseJpaR4Test.createConceptMap());
+ return convertConceptMap(BaseJpaR4Test.createConceptMap());
} catch (FHIRException fe) {
throw new InternalErrorException(fe);
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java
index 4ba4f35f181..b85abe96435 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java
@@ -9,6 +9,7 @@ import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl;
+import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.TokenParamModifier;
@@ -134,8 +135,13 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
}
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table);
+
+ myTermDeferredStorageSvc.saveAllDeferred();
}
+ @Autowired
+ private ITermDeferredStorageSvc myTermDeferredStorageSvc;
+
private void createExternalCsAndLocalVs() {
CodeSystem codeSystem = createExternalCs();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java
index 3619811ca47..55b8c5bf988 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java
@@ -99,7 +99,7 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test {
myValueSetDao.create(vs);
ValueSet expansion = myValueSetDao.expandByIdentifier("http://ccim.on.ca/fhir/iar/ValueSet/iar-citizenship-status", null);
- ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion));
+ ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion));
// Questionnaire q = loadResourceFromClasspath(Questionnaire.class,"/dstu3/iar/Questionnaire-iar-test.xml" );
// myQuestionnaireDao.create(q);
@@ -326,11 +326,11 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test {
myObservationDao.validate(input, null, encoded, EncodingEnum.JSON, mode, null, mySrd);
fail();
} catch (PreconditionFailedException e) {
- String ooString = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome());
- ourLog.info(ooString);
- assertThat(ooString, containsString("StructureDefinition reference \\\"" + profileUri + "\\\" could not be resolved"));
+ OperationOutcome oo = (OperationOutcome) e.getOperationOutcome();
+ String outputString = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(oo);
+ ourLog.info(outputString);
+ assertThat(outputString, containsString("Profile reference 'http://example.com/StructureDefinition/testValidateResourceContainingProfileDeclarationInvalid' could not be resolved, so has not been checked"));
}
-
}
@Test
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java
index a3f8a136228..26f5bd9b4da 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java
@@ -162,6 +162,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
@Qualifier("myConditionDaoR4")
protected IFhirResourceDao myConditionDao;
@Autowired
+ @Qualifier("myEpisodeOfCareDaoR4")
+ protected IFhirResourceDao myEpisodeOfCareDao;
+ @Autowired
protected DaoConfig myDaoConfig;
@Autowired
protected ModelConfig myModelConfig;
@@ -169,6 +172,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
@Qualifier("myDeviceDaoR4")
protected IFhirResourceDao myDeviceDao;
@Autowired
+ @Qualifier("myProvenanceDaoR4")
+ protected IFhirResourceDao myProvenanceDao;
+ @Autowired
@Qualifier("myDiagnosticReportDaoR4")
protected IFhirResourceDao myDiagnosticReportDao;
@Autowired
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java
index ee059080b41..2b5380886de 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java
@@ -133,6 +133,38 @@ public class FhirResourceDaoR4QueryCountTest extends BaseJpaR4Test {
assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
}
+
+ @Test
+ public void testCreateWithClientAssignedId() {
+ myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.DISABLED);
+
+ runInTransaction(() -> {
+ Patient p = new Patient();
+ p.getMaritalStatus().setText("123");
+ return myPatientDao.create(p).getId().toUnqualified();
+ });
+
+ myCaptureQueriesListener.clear();
+
+ runInTransaction(() -> {
+ Patient p = new Patient();
+ p.setId("AAA");
+ p.getMaritalStatus().setText("123");
+ return myPatientDao.update(p).getId().toUnqualified();
+ });
+
+ myCaptureQueriesListener.logSelectQueriesForCurrentThread();
+ assertEquals(1, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
+ myCaptureQueriesListener.logUpdateQueriesForCurrentThread();
+ assertEquals(0, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size());
+ myCaptureQueriesListener.logInsertQueriesForCurrentThread();
+ assertEquals(4, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size());
+ myCaptureQueriesListener.logDeleteQueriesForCurrentThread();
+ assertEquals(0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
+ }
+
+
+
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java
index c5d952df13c..86822895a5f 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java
@@ -3,7 +3,14 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.entity.Search;
-import ca.uhn.fhir.jpa.model.entity.*;
+import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
+import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
+import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
+import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
+import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
+import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
+import ca.uhn.fhir.jpa.model.entity.ResourceLink;
+import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
@@ -33,7 +40,11 @@ import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
import org.hl7.fhir.r4.model.Observation.ObservationStatus;
import org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType;
import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus;
-import org.junit.*;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
@@ -44,12 +55,30 @@ import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
-import java.util.*;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
import java.util.stream.Collectors;
import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.hasItems;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
@SuppressWarnings({"unchecked", "Duplicates"})
@@ -73,6 +102,28 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
}
+ @Test
+ public void testCanonicalReference() {
+ StructureDefinition sd = new StructureDefinition();
+ sd.getSnapshot().addElement().getBinding().setValueSet("http://foo");
+ String id = myStructureDefinitionDao.create(sd).getId().toUnqualifiedVersionless().getValue();
+
+ {
+ SearchParameterMap map = new SearchParameterMap();
+ map.setLoadSynchronous(true);
+ map.add(StructureDefinition.SP_VALUESET, new ReferenceParam("http://foo"));
+ List ids = toUnqualifiedVersionlessIdValues(myStructureDefinitionDao.search(map));
+ assertThat(ids, contains(id));
+ }
+ {
+ SearchParameterMap map = new SearchParameterMap();
+ map.setLoadSynchronous(true);
+ map.add(StructureDefinition.SP_VALUESET, new ReferenceParam("http://foo2"));
+ List ids = toUnqualifiedVersionlessIdValues(myStructureDefinitionDao.search(map));
+ assertThat(ids, empty());
+ }
+ }
+
@Test
public void testHasConditionAgeCompare() {
Patient patient = new Patient();
@@ -569,6 +620,41 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
}
+ @Test
+ public void testHasLimitsByType() {
+
+ Patient patient = new Patient();
+ patient.setActive(true);
+ IIdType patientId = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
+
+ Encounter encounter = new Encounter();
+ encounter.setStatus(Encounter.EncounterStatus.ARRIVED);
+ IIdType encounterId = myEncounterDao.create(encounter).getId().toUnqualifiedVersionless();
+
+ Device device = new Device();
+ device.setManufacturer("Acme");
+ IIdType deviceId = myDeviceDao.create(device).getId().toUnqualifiedVersionless();
+
+ Provenance provenance = new Provenance();
+ provenance.addTarget().setReferenceElement(patientId);
+ provenance.addTarget().setReferenceElement(encounterId);
+ provenance.addAgent().setWho(new Reference(deviceId));
+ myProvenanceDao.create(provenance);
+
+ String criteria = "_has:Provenance:target:agent=" + deviceId.getValue();
+ SearchParameterMap map = myMatchUrlService.translateMatchUrl(criteria, myFhirCtx.getResourceDefinition(Encounter.class));
+
+ map.setLoadSynchronous(true);
+
+ myCaptureQueriesListener.clear();
+ IBundleProvider results = myEncounterDao.search(map);
+ myCaptureQueriesListener.logSelectQueriesForCurrentThread(0);
+
+ List ids = toUnqualifiedVersionlessIdValues(results);
+ assertThat(ids, containsInAnyOrder(encounterId.getValue()));
+
+ }
+
@Test
public void testHasParameter() {
IIdType pid0;
@@ -3258,6 +3344,105 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
}
}
+ @Test
+ public void testSearchWithDateAndReusesExistingJoin() {
+ // Add a search parameter to Observation.issued, so that between that one
+ // and the existing one on Observation.effective, we have 2 date search parameters
+ // on the same resource
+ {
+ SearchParameter sp = new SearchParameter();
+ sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
+ sp.addBase("Observation");
+ sp.setType(Enumerations.SearchParamType.DATE);
+ sp.setCode("issued");
+ sp.setExpression("Observation.issued");
+ mySearchParameterDao.create(sp);
+ mySearchParamRegistry.forceRefresh();
+ }
+
+ // Dates are reversed on these two observations
+ IIdType obsId1;
+ {
+ Observation obs = new Observation();
+ obs.setIssuedElement(new InstantType("2020-06-06T12:00:00Z"));
+ obs.setEffective(new InstantType("2019-06-06T12:00:00Z"));
+ obsId1 = myObservationDao.create(obs).getId().toUnqualifiedVersionless();
+ }
+ IIdType obsId2;
+ {
+ Observation obs = new Observation();
+ obs.setIssuedElement(new InstantType("2019-06-06T12:00:00Z"));
+ obs.setEffective(new InstantType("2020-06-06T12:00:00Z"));
+ obsId2 = myObservationDao.create(obs).getId().toUnqualifiedVersionless();
+ }
+
+ // Add two with a period
+ IIdType obsId3;
+ {
+ Observation obs = new Observation();
+ obs.setEffective(new Period().setStartElement(new DateTimeType("2000-06-06T12:00:00Z")).setEndElement(new DateTimeType("2001-06-06T12:00:00Z")));
+ obsId3 = myObservationDao.create(obs).getId().toUnqualifiedVersionless();
+ }
+ IIdType obsId4;
+ {
+ Observation obs = new Observation();
+ obs.setEffective(new Period().setStartElement(new DateTimeType("2001-01-01T12:00:00Z")).setEndElement(new DateTimeType("2002-01-01T12:00:00Z")));
+ obsId4 = myObservationDao.create(obs).getId().toUnqualifiedVersionless();
+ }
+
+ // Two AND instances of 1 SP
+ {
+ myCaptureQueriesListener.clear();
+ SearchParameterMap params = new SearchParameterMap();
+ params.setLoadSynchronous(true);
+ params.add("issued", new DateParam("ge2020-06-05"));
+ params.add("issued", new DateParam("lt2020-06-07"));
+ List patients = toUnqualifiedVersionlessIds(myObservationDao.search(params));
+ assertThat(patients.toString(), patients, contains(obsId1));
+ String searchQuery = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
+ ourLog.info("Search query:\n{}", searchQuery);
+ assertEquals(searchQuery, 1, StringUtils.countMatches(searchQuery.toLowerCase(), "join"));
+ assertEquals(searchQuery, 1, StringUtils.countMatches(searchQuery.toLowerCase(), "hash_identity"));
+ assertEquals(searchQuery, 2, StringUtils.countMatches(searchQuery.toLowerCase(), "sp_value_low"));
+ }
+
+ // Two AND instances of 1 SP and 1 instance of another
+ {
+ myCaptureQueriesListener.clear();
+ SearchParameterMap params = new SearchParameterMap();
+ params.setLoadSynchronous(true);
+ params.add("issued", new DateParam("ge2020-06-05"));
+ params.add("issued", new DateParam("lt2020-06-07"));
+ params.add("date", new DateParam("gt2019-06-05"));
+ params.add("date", new DateParam("lt2019-06-07"));
+ List patients = toUnqualifiedVersionlessIds(myObservationDao.search(params));
+ assertThat(patients.toString(), patients, contains(obsId1));
+ String searchQuery = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
+ ourLog.info("Search query:\n{}", searchQuery);
+ assertEquals(searchQuery, 2, StringUtils.countMatches(searchQuery.toLowerCase(), "join"));
+ assertEquals(searchQuery, 2, StringUtils.countMatches(searchQuery.toLowerCase(), "hash_identity"));
+ assertEquals(searchQuery, 4, StringUtils.countMatches(searchQuery.toLowerCase(), "sp_value_low"));
+ }
+
+ // Period search
+ {
+ myCaptureQueriesListener.clear();
+ SearchParameterMap params = new SearchParameterMap();
+ params.setLoadSynchronous(true);
+ params.add("date", new DateParam("lt2002-01-01T12:00:00Z"));
+ List patients = toUnqualifiedVersionlessIds(myObservationDao.search(params));
+ assertThat(patients.toString(), patients, containsInAnyOrder(obsId3, obsId4));
+ String searchQuery = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
+ ourLog.info("Search query:\n{}", searchQuery);
+ assertEquals(searchQuery, 1, StringUtils.countMatches(searchQuery.toLowerCase(), "join"));
+ assertEquals(searchQuery, 1, StringUtils.countMatches(searchQuery.toLowerCase(), "hash_identity"));
+ assertEquals(searchQuery, 1, StringUtils.countMatches(searchQuery.toLowerCase(), "sp_value_low"));
+ }
+
+ }
+
+
+
@Test
public void testSearchWithFetchSizeDefaultMaximum() {
myDaoConfig.setFetchSizeDefaultMaximum(5);
@@ -4228,6 +4413,44 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
}
}
+ @Test
+ public void testCircularReferencesDontBreakRevIncludes() {
+
+ Patient p = new Patient();
+ p.setActive(true);
+ IIdType patientId = myPatientDao.create(p).getId().toUnqualifiedVersionless();
+
+ Encounter enc = new Encounter();
+ enc.setStatus(Encounter.EncounterStatus.ARRIVED);
+ enc.getSubject().setReference(patientId.getValue());
+ IIdType encId = myEncounterDao.create(enc).getId().toUnqualifiedVersionless();
+
+ Condition cond = new Condition();
+ cond.addIdentifier().setSystem("http://foo").setValue("123");
+ IIdType conditionId = myConditionDao.create(cond).getId().toUnqualifiedVersionless();
+
+ EpisodeOfCare ep = new EpisodeOfCare();
+ ep.setStatus(EpisodeOfCare.EpisodeOfCareStatus.ACTIVE);
+ IIdType epId = myEpisodeOfCareDao.create(ep).getId().toUnqualifiedVersionless();
+
+ enc.getEpisodeOfCareFirstRep().setReference(ep.getId());
+ myEncounterDao.update(enc);
+ cond.getEncounter().setReference(enc.getId());
+ myConditionDao.update(cond);
+ ep.getDiagnosisFirstRep().getCondition().setReference(cond.getId());
+ myEpisodeOfCareDao.update(ep);
+
+ // Search time
+ SearchParameterMap params = new SearchParameterMap();
+ params.setLoadSynchronous(true);
+ params.addRevInclude(new Include("*").setRecurse(true));
+ IBundleProvider results = myPatientDao.search(params);
+ List values = toUnqualifiedVersionlessIdValues(results);
+ assertThat(values.toString(), values, containsInAnyOrder(patientId.getValue(), encId.getValue(), conditionId.getValue(), epId.getValue()));
+
+ }
+
+
private String toStringMultiline(List> theResults) {
StringBuilder b = new StringBuilder();
for (Object next : theResults) {
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java
index a446d5e9440..590e86b89a3 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java
@@ -30,7 +30,6 @@ import org.junit.Test;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean;
-import org.springframework.test.context.TestPropertySource;
import java.util.ArrayList;
import java.util.Arrays;
@@ -163,7 +162,7 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test {
}
@Test
- public void testFetchTotalAccurateForSlowLoading() throws InterruptedException {
+ public void testFetchTotalAccurateForSlowLoading() {
create200Patients();
mySearchCoordinatorSvcImpl.setLoadingThrottleForUnitTests(25);
@@ -836,8 +835,6 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test {
assertEquals(1, myCaptureQueriesListener.countSelectQueriesForCurrentThread());
assertEquals(4, myCaptureQueriesListener.countInsertQueriesForCurrentThread());
assertEquals(0, myCaptureQueriesListener.countDeleteQueriesForCurrentThread());
- // Because of the forced ID's bidirectional link HFJ_RESOURCE <-> HFJ_FORCED_ID
- assertEquals(1, myCaptureQueriesListener.countUpdateQueriesForCurrentThread());
runInTransaction(() -> {
assertEquals(1, myResourceTableDao.count());
assertEquals(1, myResourceHistoryTableDao.count());
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchTest.java
index 23ee3628fc5..26fbb97b9ab 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchTest.java
@@ -23,6 +23,7 @@ import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult;
+import org.hamcrest.Matchers;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.*;
import org.junit.AfterClass;
@@ -37,8 +38,10 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.PlatformTransactionManager;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertEquals;
@@ -146,6 +149,53 @@ public class FhirResourceDaoR4SearchWithElasticSearchTest extends BaseJpaTest {
}
+
+ @Test
+ public void testExpandVsWithMultiInclude_All() throws IOException {
+ CodeSystem cs = loadResource(myFhirCtx, CodeSystem.class, "/r4/expand-multi-cs.json");
+ myCodeSystemDao.update(cs);
+
+ ValueSet vs = loadResource(myFhirCtx, ValueSet.class, "/r4/expand-multi-vs-all.json");
+ ValueSet expanded = myValueSetDao.expand(vs, null);
+
+ ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
+
+ // All codes
+ List codes = expanded
+ .getExpansion()
+ .getContains()
+ .stream()
+ .map(t -> t.getCode())
+ .sorted()
+ .collect(Collectors.toList());
+ assertThat(codes.toString(), codes, Matchers.contains("advice", "message", "note", "notification"));
+ }
+
+
+ @Test
+ public void testExpandVsWithMultiInclude_Some() throws IOException {
+ CodeSystem cs = loadResource(myFhirCtx, CodeSystem.class, "/r4/expand-multi-cs.json");
+ myCodeSystemDao.update(cs);
+
+ ValueSet vs = loadResource(myFhirCtx, ValueSet.class, "/r4/expand-multi-vs-all.json");
+ vs.getCompose().getInclude().get(0).getConcept().remove(0);
+ vs.getCompose().getInclude().get(0).getConcept().remove(0);
+
+ ValueSet expanded = myValueSetDao.expand(vs, null);
+
+ ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
+
+ // All codes
+ List codes = expanded
+ .getExpansion()
+ .getContains()
+ .stream()
+ .map(t -> t.getCode())
+ .sorted()
+ .collect(Collectors.toList());
+ assertThat(codes.toString(), codes, Matchers.contains("advice", "note"));
+ }
+
private CodeSystem createExternalCs() {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java
index 1b72bfc8f7e..1279ab11d4e 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java
@@ -164,6 +164,8 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
}
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
+
+ myTerminologyDeferredStorageSvc.saveAllDeferred();
}
private void createLocalCsAndVs() {
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java
index 74bfa659695..992eb5f3f83 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java
@@ -147,6 +147,8 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
}
myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://loinc.org", codesToAdd);
+ myTerminologyDeferredStorageSvc.saveAllDeferred();
+
// Create a valueset
ValueSet vs = new ValueSet();
vs.setUrl("http://example.com/fhir/ValueSet/observation-vitalsignresult");
@@ -399,12 +401,11 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
myObservationDao.validate(input, null, encoded, EncodingEnum.JSON, mode, null, mySrd);
fail();
} catch (PreconditionFailedException e) {
- String ooString = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome());
- ourLog.info(ooString);
- assertThat(ooString, containsString("StructureDefinition reference \\\"" + profileUri + "\\\" could not be resolved"));
+ org.hl7.fhir.r4.model.OperationOutcome oo = (org.hl7.fhir.r4.model.OperationOutcome) e.getOperationOutcome();
+ String outputString = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(oo);
+ ourLog.info(outputString);
+ assertThat(outputString, containsString("Profile reference 'http://example.com/StructureDefinition/testValidateResourceContainingProfileDeclarationInvalid' could not be resolved, so has not been checked"));
}
-
-
}
@Test
@@ -618,6 +619,8 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
upload("/r4/uscore/ValueSet-omb-race-category.json");
upload("/r4/uscore/ValueSet-us-core-usps-state.json");
+ myTerminologyDeferredStorageSvc.saveAllDeferred();
+
{
String resource = loadResource("/r4/uscore/patient-resource-badcode.json");
IBaseResource parsedResource = myFhirCtx.newJsonParser().parseResource(resource);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java
index ca08514295b..88c27f47a2e 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java
@@ -9,20 +9,29 @@ import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Patient;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
-import static org.hamcrest.Matchers.*;
+import static org.hamcrest.Matchers.blankOrNullString;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.core.IsNot.not;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
+ private static final Logger ourLog = LoggerFactory.getLogger(ResourceProviderR4CacheTest.class);
private CapturingInterceptor myCapturingInterceptor;
@Autowired
private ISearchDao mySearchEntityDao;
@@ -184,6 +193,39 @@ public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
assertEquals(results1.getId(), results2.getId());
}
+ @Test
+ public void testDeletedSearchResultsNotReturnedFromCache() {
+ Patient p = new Patient();
+ p.addName().setFamily("Foo");
+ String p1Id = myPatientDao.create(p).getId().toUnqualifiedVersionless().getValue();
+
+ p = new Patient();
+ p.addName().setFamily("Foo");
+ String p2Id = myPatientDao.create(p).getId().toUnqualifiedVersionless().getValue();
+
+ Bundle resp1 = ourClient
+ .search()
+ .forResource("Patient")
+ .where(Patient.NAME.matches().value("foo"))
+ .returnBundle(Bundle.class)
+ .execute();
+ assertEquals(2, resp1.getEntry().size());
+
+ ourClient.delete().resourceById(new IdType(p1Id)).execute();
+
+ Bundle resp2 = ourClient
+ .search()
+ .forResource("Patient")
+ .where(Patient.NAME.matches().value("foo"))
+ .returnBundle(Bundle.class)
+ .execute();
+
+ assertEquals(resp1.getId(), resp2.getId());
+
+ ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp2));
+ assertEquals(1, resp2.getEntry().size());
+ }
+
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java
index a8f485ba05d..186a023026c 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java
@@ -15,6 +15,7 @@ import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.parser.StrictErrorHandler;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.*;
+import ca.uhn.fhir.rest.client.apache.ResourceEntity;
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
@@ -26,6 +27,9 @@ import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.UrlUtil;
+import ca.uhn.fhir.validation.ResultSeverityEnum;
+import ca.uhn.fhir.validation.SingleValidationMessage;
+import ca.uhn.fhir.validation.ValidationResult;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import org.apache.commons.io.IOUtils;
@@ -52,6 +56,7 @@ import org.hl7.fhir.r4.model.Observation.ObservationStatus;
import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemType;
import org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType;
import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus;
+import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.junit.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.util.AopTestUtils;
@@ -2260,6 +2265,28 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
}
}
+
+ @Test
+ public void testValidateResourceContainingProfileDeclarationDoesntResolve() throws IOException {
+ Observation input = new Observation();
+ input.getText().setDiv(new XhtmlNode().setValue("AA")).setStatus(Narrative.NarrativeStatus.GENERATED);
+ input.getMeta().addProfile("http://foo/structuredefinition/myprofile");
+
+ input.getCode().setText("Hello");
+ input.setStatus(ObservationStatus.FINAL);
+
+ HttpPost post = new HttpPost(ourServerBase + "/Observation/$validate?_pretty=true");
+ post.setEntity(new ResourceEntity(myFhirCtx, input));
+
+ try (CloseableHttpResponse resp = ourHttpClient.execute(post)) {
+ String respString = IOUtils.toString(resp.getEntity().getContent(), Charsets.UTF_8);
+ ourLog.info(respString);
+ assertEquals(412, resp.getStatusLine().getStatusCode());
+ assertThat(respString, containsString("Profile reference 'http://foo/structuredefinition/myprofile' could not be resolved, so has not been checked"));
+ }
+ }
+
+
@SuppressWarnings("unused")
@Test
public void testFullTextSearch() throws Exception {
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImplTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImplTest.java
index c3efb07cdc8..a622a7a4933 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImplTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImplTest.java
@@ -182,33 +182,11 @@ public class SearchCoordinatorSvcImplTest {
when(mySearchBuilder.createQuery(any(), any(), any())).thenReturn(iter);
doAnswer(loadPids()).when(mySearchBuilder).loadResourcesByPid(any(Collection.class), any(Collection.class), any(List.class), anyBoolean(), any());
- when(mySearchResultCacheSvc.fetchResultPids(any(), anyInt(), anyInt())).thenAnswer(t -> {
- List returnedValues = iter.getReturnedValues();
- int offset = t.getArgument(1, Integer.class);
- int end = t.getArgument(2, Integer.class);
- end = Math.min(end, returnedValues.size());
- offset = Math.min(offset, returnedValues.size());
- ourLog.info("findWithSearchUuid {} - {} out of {} values", offset, end, returnedValues.size());
- return returnedValues.subList(offset, end);
- });
-
- when(mySearchResultCacheSvc.fetchAllResultPids(any())).thenReturn(allResults);
-
- when(mySearchCacheSvc.tryToMarkSearchAsInProgress(any())).thenAnswer(t->{
- Search search = t.getArgument(0, Search.class);
- assertEquals(SearchStatusEnum.PASSCMPLET, search.getStatus());
- search.setStatus(SearchStatusEnum.LOADING);
- return Optional.of(search);
- });
-
when(mySearchCacheSvc.save(any())).thenAnswer(t -> {
Search search = t.getArgument(0, Search.class);
myCurrentSearch = search;
return search;
});
- when(mySearchCacheSvc.fetchByUuid(any())).thenAnswer(t -> Optional.ofNullable(myCurrentSearch));
- IFhirResourceDao dao = myCallingDao;
- when(myDaoRegistry.getResourceDao(any(String.class))).thenReturn(dao);
IBundleProvider result = mySvc.registerSearch(myCallingDao, params, "Patient", new CacheControlDirective(), null);
assertNotNull(result.getUuid());
@@ -602,6 +580,11 @@ public class SearchCoordinatorSvcImplTest {
return myWrap.getSkippedCount();
}
+ @Override
+ public int getNonSkippedCount() {
+ return myCount;
+ }
+
@Override
public void close() {
// nothing
@@ -611,6 +594,7 @@ public class SearchCoordinatorSvcImplTest {
public static class ResultIterator extends BaseIterator implements IResultIterator {
private final Iterator myWrap;
+ private int myCount;
ResultIterator(Iterator theWrap) {
myWrap = theWrap;
@@ -623,6 +607,7 @@ public class SearchCoordinatorSvcImplTest {
@Override
public ResourcePersistentId next() {
+ myCount++;
return myWrap.next();
}
@@ -631,6 +616,11 @@ public class SearchCoordinatorSvcImplTest {
return 0;
}
+ @Override
+ public int getNonSkippedCount() {
+ return myCount;
+ }
+
@Override
public void close() {
// nothing
@@ -697,6 +687,11 @@ public class SearchCoordinatorSvcImplTest {
}
}
+ @Override
+ public int getNonSkippedCount() {
+ return 0;
+ }
+
@Override
public void close() {
// nothing
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcDeltaR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcDeltaR4Test.java
index 496296a12ab..5f89fb013a6 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcDeltaR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcDeltaR4Test.java
@@ -1,10 +1,12 @@
package ca.uhn.fhir.jpa.term;
import ca.uhn.fhir.context.support.IContextValidationSupport;
+import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
+import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.UriParam;
@@ -16,25 +18,36 @@ import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.ValueSet;
+import org.junit.After;
import org.junit.AfterClass;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
+import static org.apache.commons.lang3.StringUtils.countMatches;
import static org.apache.commons.lang3.StringUtils.leftPad;
import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.Matchers.matchesPattern;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class TerminologySvcDeltaR4Test extends BaseJpaR4Test {
private static final Logger ourLog = LoggerFactory.getLogger(TerminologySvcDeltaR4Test.class);
+ @After
+ public void after() {
+ myDaoConfig.setDeferIndexingForCodesystemsOfSize(new DaoConfig().getDeferIndexingForCodesystemsOfSize());
+ }
+
@Test
public void testAddRootConcepts() {
@@ -115,17 +128,23 @@ public class TerminologySvcDeltaR4Test extends BaseJpaR4Test {
ourLog.info("All concepts: {}", myTermConceptDao.findAll());
});
+ myCaptureQueriesListener.clear();
+
delta = new CustomTerminologySet();
TermConcept root = delta.addRootConcept("RootA", "Root A");
root.addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("ChildAA").setDisplay("Child AA");
root.addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("ChildAB").setDisplay("Child AB");
myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://foo/cs", delta);
+
+ myCaptureQueriesListener.logAllQueriesForCurrentThread();
+
assertHierarchyContains(
"RootA seq=0",
" ChildAA seq=0",
" ChildAB seq=1",
"RootB seq=0"
);
+
}
@Test
@@ -156,12 +175,86 @@ public class TerminologySvcDeltaR4Test extends BaseJpaR4Test {
outcome = myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://foo/cs", delta);
assertHierarchyContains(
"RootA seq=0",
+ " ChildAA seq=0",
+ " ChildAAA seq=0",
"RootB seq=0",
" ChildAA seq=0",
" ChildAAA seq=0"
);
assertEquals(2, outcome.getUpdatedConceptCount());
+ runInTransaction(() -> {
+ TermConcept concept = myTermSvc.findCode("http://foo/cs", "ChildAA").orElseThrow(() -> new IllegalStateException());
+ assertEquals(2, concept.getParents().size());
+ assertThat(concept.getParentPidsAsString(), matchesPattern("^[0-9]+ [0-9]+$"));
+ });
+
+ }
+
+ @Test
+ public void testReAddingConceptsDoesntRecreateExistingLinks() {
+ createNotPresentCodeSystem();
+ assertHierarchyContains();
+
+ UploadStatistics outcome;
+ CustomTerminologySet delta;
+
+ myCaptureQueriesListener.clear();
+
+ delta = new CustomTerminologySet();
+ delta.addRootConcept("RootA", "Root A")
+ .addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("ChildAA").setDisplay("Child AA");
+ myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://foo/cs", delta);
+ assertHierarchyContains(
+ "RootA seq=0",
+ " ChildAA seq=0"
+ );
+
+ myCaptureQueriesListener.logDeleteQueries();
+ assertEquals(0, myCaptureQueriesListener.countDeleteQueries());
+ myCaptureQueriesListener.logInsertQueries();
+ // 2 concepts, 1 link
+ assertEquals(3, myCaptureQueriesListener.countInsertQueries());
+ myCaptureQueriesListener.clear();
+
+ delta = new CustomTerminologySet();
+ delta.addRootConcept("RootA", "Root A")
+ .addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("ChildAA").setDisplay("Child AA")
+ .addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("ChildAAA").setDisplay("Child AAA");
+ myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://foo/cs", delta);
+ assertHierarchyContains(
+ "RootA seq=0",
+ " ChildAA seq=0",
+ " ChildAAA seq=0"
+ );
+
+ myCaptureQueriesListener.logDeleteQueries();
+ assertEquals(0, myCaptureQueriesListener.countDeleteQueries());
+ myCaptureQueriesListener.logInsertQueries();
+ // 1 concept, 1 link
+ assertEquals(2, myCaptureQueriesListener.countInsertQueries());
+ myCaptureQueriesListener.clear();
+
+ delta = new CustomTerminologySet();
+ delta.addRootConcept("RootA", "Root A")
+ .addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("ChildAA").setDisplay("Child AA")
+ .addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("ChildAAA").setDisplay("Child AAA")
+ .addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("ChildAAAA").setDisplay("Child AAAA");
+ myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://foo/cs", delta);
+ assertHierarchyContains(
+ "RootA seq=0",
+ " ChildAA seq=0",
+ " ChildAAA seq=0",
+ " ChildAAAA seq=0"
+ );
+
+ myCaptureQueriesListener.logDeleteQueries();
+ assertEquals(0, myCaptureQueriesListener.countDeleteQueries());
+ myCaptureQueriesListener.logInsertQueries();
+ // 1 concept, 1 link
+ assertEquals(2, myCaptureQueriesListener.countInsertQueries());
+ myCaptureQueriesListener.clear();
+
}
@Test
@@ -281,6 +374,49 @@ public class TerminologySvcDeltaR4Test extends BaseJpaR4Test {
}
+ @Test
+ public void testAddLargeHierarchy() {
+ myDaoConfig.setDeferIndexingForCodesystemsOfSize(5);
+
+ createNotPresentCodeSystem();
+ ValueSet vs;
+ vs = expandNotPresentCodeSystem();
+ assertEquals(0, vs.getExpansion().getContains().size());
+
+ CustomTerminologySet delta = new CustomTerminologySet();
+
+ // Create a nice deep hierarchy
+ TermConcept concept = delta.addRootConcept("Root", "Root");
+ int nestedDepth = 10;
+ for (int i = 0; i < nestedDepth; i++) {
+ String name = concept.getCode();
+ concept = concept.addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode(name + "0").setDisplay(name + "0");
+ }
+
+ myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://foo/cs", delta);
+
+ assertFalse(myTermDeferredStorageSvc.isStorageQueueEmpty());
+ while (!myTermDeferredStorageSvc.isStorageQueueEmpty()) {
+ myTermDeferredStorageSvc.saveDeferred();
+ }
+
+ List expectedHierarchy = new ArrayList<>();
+ for (int i = 0; i < nestedDepth + 1; i++) {
+ String expected = leftPad("", i, " ") +
+ "Root" +
+ leftPad("", i, "0") +
+ " seq=0";
+ expectedHierarchy.add(expected);
+ }
+
+ assertHierarchyContains(expectedHierarchy.toArray(new String[0]));
+
+ }
+
+ @Autowired
+ private ITermDeferredStorageSvc myTermDeferredStorageSvc;
+
+
@Test
public void testAddModifiesExistingCodesInPlace() {
@@ -307,54 +443,6 @@ public class TerminologySvcDeltaR4Test extends BaseJpaR4Test {
assertEquals("CODEA1", myTermSvc.lookupCode(myFhirCtx, "http://foo", "codea").getCodeDisplay());
}
- @Test
- public void testAddRelocateHierarchy() {
- createNotPresentCodeSystem();
-
- // Add code hierarchy
- CustomTerminologySet delta = new CustomTerminologySet();
- TermConcept codeA = delta.addRootConcept("CodeA", "Code A");
- TermConcept codeAA = codeA.addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("CodeAA").setDisplay("Code AA");
- codeAA.addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("CodeAAA").setDisplay("Code AAA");
- codeAA.addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("CodeAAB").setDisplay("Code AAB");
- TermConcept codeB = delta.addRootConcept("CodeB", "Code B");
- TermConcept codeBA = codeB.addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("CodeBA").setDisplay("Code BA");
- codeBA.addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("CodeBAA").setDisplay("Code BAA");
- codeBA.addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("CodeBAB").setDisplay("Code BAB");
- UploadStatistics outcome = myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://foo/cs", delta);
- assertEquals(8, outcome.getUpdatedConceptCount());
- assertHierarchyContains(
- "CodeA seq=0",
- " CodeAA seq=0",
- " CodeAAA seq=0",
- " CodeAAB seq=1",
- "CodeB seq=0",
- " CodeBA seq=0",
- " CodeBAA seq=0",
- " CodeBAB seq=1"
- );
-
- // Move a single child code to a new spot and make sure the hierarchy comes along
- // for the ride..
- delta = new CustomTerminologySet();
- delta
- .addRootConcept("CodeB", "Code B")
- .addChild(TermConceptParentChildLink.RelationshipTypeEnum.ISA).setCode("CodeAA").setDisplay("Code AA");
- outcome = myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://foo/cs", delta);
- assertEquals(2, outcome.getUpdatedConceptCount());
- assertHierarchyContains(
- "CodeA seq=0",
- "CodeB seq=0",
- " CodeBA seq=0",
- " CodeBAA seq=0",
- " CodeBAB seq=1",
- " CodeAA seq=0", // <-- CodeAA got added here so it comes second
- " CodeAAA seq=0",
- " CodeAAB seq=1"
- );
-
- }
-
@Test
@Ignore
public void testAddWithPropertiesAndDesignations() {
@@ -464,9 +552,15 @@ public class TerminologySvcDeltaR4Test extends BaseJpaR4Test {
assertEquals(true, runInTransaction(() -> myTermSvc.findCode("http://foo/cs", "codeAAA").isPresent()));
// Remove CodeA
- delta = new CustomTerminologySet();
- delta.addRootConcept("codeA");
- myTermCodeSystemStorageSvc.applyDeltaCodeSystemsRemove("http://foo/cs", delta);
+ myCaptureQueriesListener.clear();
+ runInTransaction(()->{
+ CustomTerminologySet delta2 = new CustomTerminologySet();
+ delta2.addRootConcept("codeA");
+ myTermCodeSystemStorageSvc.applyDeltaCodeSystemsRemove("http://foo/cs", delta2);
+ });
+ myCaptureQueriesListener.logAllQueriesForCurrentThread();
+
+ ourLog.info("*** Done removing");
assertEquals(false, runInTransaction(() -> myTermSvc.findCode("http://foo/cs", "codeB").isPresent()));
assertEquals(false, runInTransaction(() -> myTermSvc.findCode("http://foo/cs", "codeA").isPresent()));
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu3Test.java
index 3f2e784734a..7c3f2efaf78 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu3Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu3Test.java
@@ -100,6 +100,8 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
+ myTerminologyDeferredStorageSvc.saveAllDeferred();
+
return id;
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/validator/ValidatorAcrossVersionsTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/validator/ValidatorAcrossVersionsTest.java
index c335a1ac6ea..87fcc302bba 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/validator/ValidatorAcrossVersionsTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/validator/ValidatorAcrossVersionsTest.java
@@ -54,8 +54,8 @@ public class ValidatorAcrossVersionsTest {
ourLog.info(ctxDstu2.newJsonParser().setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome()));
assertEquals(2, result.getMessages().size());
- assertEquals("No questionnaire is identified, so no validation can be performed against the base questionnaire", result.getMessages().get(0).getMessage());
- assertEquals("Profile http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse, Element 'QuestionnaireResponse.status': minimum required = 1, but only found 0", result.getMessages().get(1).getMessage());
+ assertEquals("Profile http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse, Element 'QuestionnaireResponse.status': minimum required = 1, but only found 0", result.getMessages().get(0).getMessage());
+ assertEquals("No questionnaire is identified, so no validation can be performed against the base questionnaire", result.getMessages().get(1).getMessage());
}
}
diff --git a/hapi-fhir-jpaserver-base/src/test/resources/r4/expand-multi-cs.json b/hapi-fhir-jpaserver-base/src/test/resources/r4/expand-multi-cs.json
new file mode 100644
index 00000000000..ea72cd32b04
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/test/resources/r4/expand-multi-cs.json
@@ -0,0 +1,86 @@
+{
+ "resourceType" : "CodeSystem",
+ "id" : "ehealth-message-category",
+ "text" : {
+ "status" : "generated",
+ "div" : "MessageCategory
Message category types
\nThis code system http://ehealth.sundhed.dk/cs/message-category defines the following codes:
Code Display Definition message Message notification Notification advice Advice note Note
"
+ },
+ "url" : "http://ehealth.sundhed.dk/cs/message-category",
+ "version" : "0.6.0",
+ "name" : "MessageCategory",
+ "status" : "active",
+ "experimental" : false,
+ "date" : "2019-01-29T00:00:00+00:00",
+ "publisher" : "ehealth.sundhed.dk",
+ "contact" : [
+ {
+ "telecom" : [
+ {
+ "system" : "url",
+ "value" : "http://ehealth.sundhed.dk/terminology"
+ }
+ ]
+ }
+ ],
+ "description" : "Message category types",
+ "caseSensitive" : true,
+ "content" : "complete",
+ "concept" : [
+ {
+ "code" : "message",
+ "display" : "Message",
+ "designation" : [
+ {
+ "language" : "en-US",
+ "value" : "Message"
+ },
+ {
+ "language" : "da",
+ "value" : "Besked"
+ }
+ ]
+ },
+ {
+ "code" : "notification",
+ "display" : "Notification",
+ "designation" : [
+ {
+ "language" : "en-US",
+ "value" : "Notification"
+ },
+ {
+ "language" : "da",
+ "value" : "Notifikation"
+ }
+ ]
+ },
+ {
+ "code" : "advice",
+ "display" : "Advice",
+ "designation" : [
+ {
+ "language" : "en-US",
+ "value" : "Advice"
+ },
+ {
+ "language" : "da",
+ "value" : "Advisering"
+ }
+ ]
+ },
+ {
+ "code" : "note",
+ "display" : "Note",
+ "designation" : [
+ {
+ "language" : "en-US",
+ "value" : "Note"
+ },
+ {
+ "language" : "da",
+ "value" : "Note"
+ }
+ ]
+ }
+ ]
+}
diff --git a/hapi-fhir-jpaserver-base/src/test/resources/r4/expand-multi-vs-all.json b/hapi-fhir-jpaserver-base/src/test/resources/r4/expand-multi-vs-all.json
new file mode 100644
index 00000000000..817b38cbe78
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/test/resources/r4/expand-multi-vs-all.json
@@ -0,0 +1,92 @@
+{
+ "resourceType" : "ValueSet",
+ "id" : "message-category",
+ "text" : {
+ "status" : "generated",
+ "div" : "MessageCategory
The set of possible message types
\nThis value set includes codes from the following code systems:
- Include these codes as defined in
http://ehealth.sundhed.dk/cs/message-category
Code Display message Message notification Notification advice Advice note Note
Additional Language Displays
Code Dansk (Danish, da) English (United States) (English (United States), en) message Besked Message notification Notifikation Notification advice Advisering Advice note Note Note
"
+ },
+ "url" : "http://ehealth.sundhed.dk/vs/message-category",
+ "version" : "0.0.1",
+ "name" : "MessageCategory",
+ "status" : "active",
+ "experimental" : true,
+ "date" : "2019-02-08T00:00:00+00:00",
+ "publisher" : "ehealth.sundhed.dk",
+ "contact" : [
+ {
+ "name" : "FUT",
+ "telecom" : [
+ {
+ "system" : "url",
+ "value" : "https://digst.dk/digital-service/digital-velfaerd/telemedicin-kol/faelles-udbud-af-telemedicin-fut/"
+ }
+ ]
+ }
+ ],
+ "description" : "The set of possible message types",
+ "compose" : {
+ "include" : [
+ {
+ "system" : "http://ehealth.sundhed.dk/cs/message-category",
+ "concept" : [
+ {
+ "code" : "message",
+ "display" : "Message",
+ "designation" : [
+ {
+ "language" : "en-US",
+ "value" : "Message"
+ },
+ {
+ "language" : "da",
+ "value" : "Besked"
+ }
+ ]
+ },
+ {
+ "code" : "notification",
+ "display" : "Notification",
+ "designation" : [
+ {
+ "language" : "en-US",
+ "value" : "Notification"
+ },
+ {
+ "language" : "da",
+ "value" : "Notifikation"
+ }
+ ]
+ },
+ {
+ "code" : "advice",
+ "display" : "Advice",
+ "designation" : [
+ {
+ "language" : "en-US",
+ "value" : "Advice"
+ },
+ {
+ "language" : "da",
+ "value" : "Advisering"
+ }
+ ]
+ },
+ {
+ "code" : "note",
+ "display" : "Note",
+ "designation" : [
+ {
+ "language" : "en-US",
+ "value" : "Note"
+ },
+ {
+ "language" : "da",
+ "value" : "Note"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/hapi-fhir-jpaserver-migrate/pom.xml b/hapi-fhir-jpaserver-migrate/pom.xml
index 345bf13d5ee..2820928227b 100644
--- a/hapi-fhir-jpaserver-migrate/pom.xml
+++ b/hapi-fhir-jpaserver-migrate/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/FlywayMigrator.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/FlywayMigrator.java
index a743ad281e7..7373e1889ee 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/FlywayMigrator.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/FlywayMigrator.java
@@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.migrate;
*/
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
+import ca.uhn.fhir.jpa.migrate.taskdef.InitializeSchemaTask;
import com.google.common.annotations.VisibleForTesting;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.MigrationInfoService;
@@ -63,6 +64,8 @@ public class FlywayMigrator extends BaseMigrator {
if (isDryRun()) {
StringBuilder statementBuilder = buildExecutedStatementsString();
ourLog.info("SQL that would be executed:\n\n***********************************\n{}***********************************", statementBuilder);
+ } else {
+ ourLog.info("Schema migrated successfully.");
}
} catch (Exception e) {
throw e;
@@ -85,7 +88,11 @@ public class FlywayMigrator extends BaseMigrator {
@Override
public void addTasks(List theTasks) {
- theTasks.forEach(this::addTask);
+ if ("true".equals(System.getProperty("unit_test_mode"))) {
+ theTasks.stream().filter(task -> task instanceof InitializeSchemaTask).forEach(this::addTask);
+ } else {
+ theTasks.forEach(this::addTask);
+ }
}
@Override
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/TaskOnlyMigrator.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/TaskOnlyMigrator.java
index e27668fd0fe..86d1d92bcd6 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/TaskOnlyMigrator.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/TaskOnlyMigrator.java
@@ -51,7 +51,11 @@ public class TaskOnlyMigrator extends BaseMigrator {
next.setConnectionProperties(connectionProperties);
try {
- ourLog.info("Executing task of type: {}", next.getClass().getSimpleName());
+ if (isDryRun()) {
+ ourLog.info("Dry run {} {}", next.getFlywayVersion(), next.getDescription());
+ } else {
+ ourLog.info("Executing {} {}", next.getFlywayVersion(), next.getDescription());
+ }
next.execute();
addExecutedStatements(next.getExecutedStatements());
} catch (SQLException e) {
@@ -61,6 +65,8 @@ public class TaskOnlyMigrator extends BaseMigrator {
if (isDryRun()) {
StringBuilder statementBuilder = buildExecutedStatementsString();
ourLog.info("SQL that would be executed:\n\n***********************************\n{}***********************************", statementBuilder);
+ } else {
+ ourLog.info("Schema migrated successfully.");
}
}
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java
index e68d1609158..696f70be553 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java
@@ -108,7 +108,9 @@ public abstract class BaseTask {
JdbcTemplate jdbcTemplate = getConnectionProperties().newJdbcTemplate();
try {
int changesCount = jdbcTemplate.update(theSql, theArguments);
- logInfo(ourLog, "SQL \"{}\" returned {}", theSql, changesCount);
+ if (!"true".equals(System.getProperty("unit_test_mode"))) {
+ logInfo(ourLog, "SQL \"{}\" returned {}", theSql, changesCount);
+ }
return changesCount;
} catch (DataAccessException e) {
if (myFailureAllowed) {
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTask.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTask.java
index 2c856eac168..e7c0481f56c 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTask.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTask.java
@@ -34,12 +34,13 @@ import java.util.Set;
public class InitializeSchemaTask extends BaseTask {
private static final Logger ourLog = LoggerFactory.getLogger(InitializeSchemaTask.class);
+
private final ISchemaInitializationProvider mySchemaInitializationProvider;
public InitializeSchemaTask(String theProductVersion, String theSchemaVersion, ISchemaInitializationProvider theSchemaInitializationProvider) {
super(theProductVersion, theSchemaVersion);
mySchemaInitializationProvider = theSchemaInitializationProvider;
- setDescription("Initialize schema");
+ setDescription("Initialize schema for " + mySchemaInitializationProvider.getSchemaDescription());
}
@Override
@@ -58,13 +59,15 @@ public class InitializeSchemaTask extends BaseTask {
return;
}
- logInfo(ourLog, "Initializing schema for {}", driverType);
+ logInfo(ourLog, "Initializing {} schema for {}", driverType, mySchemaInitializationProvider.getSchemaDescription());
List sqlStatements = mySchemaInitializationProvider.getSqlStatements(driverType);
for (String nextSql : sqlStatements) {
executeSql(null, nextSql);
}
+
+ logInfo(ourLog, "{} schema for {} initialized successfully", driverType, mySchemaInitializationProvider.getSchemaDescription());
}
@Override
@@ -77,4 +80,8 @@ public class InitializeSchemaTask extends BaseTask {
protected void generateHashCode(HashCodeBuilder theBuilder) {
theBuilder.append(mySchemaInitializationProvider);
}
+
+ public ISchemaInitializationProvider getSchemaInitializationProvider() {
+ return mySchemaInitializationProvider;
+ }
}
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java
index 41a430a2bc4..31a71c7b1f1 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java
@@ -56,16 +56,21 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks {
init360(); // 20180918 - 20181112
init400(); // 20190401 - 20190814
init410(); // 20190815 - 20191014
- init420(); // 20191015 - 20200213
- init430(); // 20200213 - present
+ init420(); // 20191015 - 20200217
+ init430(); // 20200218 - present
}
- protected void init430() {
+ protected void init430() { // 20200218 - present
Builder version = forVersion(VersionEnum.V4_3_0);
+ // Eliminate circular dependency.
+ version.onTable("HFJ_RESOURCE").dropColumn("20200218.1", "FORCED_ID_PID");
+ version.onTable("HFJ_RES_VER").dropColumn("20200218.2", "FORCED_ID_PID");
+ version.onTable("HFJ_RES_VER").addForeignKey("20200218.3", "FK_RESOURCE_HISTORY_RESOURCE").toColumn("RES_ID").references("HFJ_RESOURCE", "RES_ID");
+ version.onTable("HFJ_RES_VER").modifyColumn("20200220.1", "RES_ID").nonNullable().failureAllowed().withType(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
}
- protected void init420() { // 20191015 - present
+ protected void init420() { // 20191015 - 20200217
Builder version = forVersion(VersionEnum.V4_2_0);
// TermValueSetConceptDesignation
@@ -899,10 +904,10 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks {
}
- private void init330() { // 20180114 - 20180329
+ protected void init330() { // 20180114 - 20180329
Builder version = forVersion(VersionEnum.V3_3_0);
- version.initializeSchema("20180115.0", new SchemaInitializationProvider("/ca/uhn/hapi/fhir/jpa/docs/database", "HFJ_RESOURCE"));
+ version.initializeSchema("20180115.0", new SchemaInitializationProvider("HAPI FHIR", "/ca/uhn/hapi/fhir/jpa/docs/database", "HFJ_RESOURCE"));
Builder.BuilderWithTableName hfjResource = version.onTable("HFJ_RESOURCE");
version.startSectionWithMessage("Starting work on table: " + hfjResource.getTableName());
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/SchemaInitializationProvider.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/SchemaInitializationProvider.java
index 6e8a0c25f7e..262dbb576af 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/SchemaInitializationProvider.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/SchemaInitializationProvider.java
@@ -37,14 +37,17 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
public class SchemaInitializationProvider implements ISchemaInitializationProvider {
- private final String mySchemaFileClassPath;
+ private String mySchemaFileClassPath;
+
+ private String mySchemaDescription;
private final String mySchemaExistsIndicatorTable;
/**
* @param theSchemaFileClassPath pathname to script used to initialize schema
* @param theSchemaExistsIndicatorTable a table name we can use to determine if this schema has already been initialized
*/
- public SchemaInitializationProvider(String theSchemaFileClassPath, String theSchemaExistsIndicatorTable) {
+ public SchemaInitializationProvider(String theSchemaDescription, String theSchemaFileClassPath, String theSchemaExistsIndicatorTable) {
+ mySchemaDescription = theSchemaDescription;
mySchemaFileClassPath = theSchemaFileClassPath;
mySchemaExistsIndicatorTable = theSchemaExistsIndicatorTable;
}
@@ -110,5 +113,21 @@ public class SchemaInitializationProvider implements ISchemaInitializationProvid
public String getSchemaExistsIndicatorTable() {
return mySchemaExistsIndicatorTable;
}
+
+ public SchemaInitializationProvider setSchemaFileClassPath(String theSchemaFileClassPath) {
+ mySchemaFileClassPath = theSchemaFileClassPath;
+ return this;
+ }
+
+ @Override
+ public String getSchemaDescription() {
+ return mySchemaDescription;
+ }
+
+ @Override
+ public SchemaInitializationProvider setSchemaDescription(String theSchemaDescription) {
+ mySchemaDescription = theSchemaDescription;
+ return this;
+ }
}
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/BaseMigrationTasks.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/BaseMigrationTasks.java
index 5d7c819744c..7198767ee0e 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/BaseMigrationTasks.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/BaseMigrationTasks.java
@@ -81,6 +81,13 @@ public class BaseMigrationTasks {
return retval;
}
+ protected BaseTask getTaskWithVersion(String theFlywayVersion) {
+ return myTasks.values().stream()
+ .filter(task -> theFlywayVersion.equals(task.getFlywayVersion()))
+ .findFirst()
+ .get();
+ }
+
void validate(Collection theTasks) {
for (BaseTask task: theTasks) {
task.validateVersion();
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/ISchemaInitializationProvider.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/ISchemaInitializationProvider.java
index b645498c9bc..1be30796e25 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/ISchemaInitializationProvider.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/ISchemaInitializationProvider.java
@@ -25,7 +25,12 @@ import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
import java.util.List;
public interface ISchemaInitializationProvider {
+
List getSqlStatements(DriverTypeEnum theDriverType);
String getSchemaExistsIndicatorTable();
+
+ String getSchemaDescription();
+
+ ISchemaInitializationProvider setSchemaDescription(String theSchemaDescription);
}
diff --git a/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTaskTest.java b/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTaskTest.java
index a55cd045f9d..c65bcb06006 100644
--- a/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTaskTest.java
+++ b/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTaskTest.java
@@ -40,6 +40,16 @@ public class InitializeSchemaTaskTest extends BaseTest {
return "DONT_MATCH_ME";
}
+ @Override
+ public String getSchemaDescription() {
+ return "TEST";
+ }
+
+ @Override
+ public ISchemaInitializationProvider setSchemaDescription(String theSchemaDescription) {
+ return this;
+ }
+
@Override
public boolean equals(Object theO) {
if (this == theO) return true;
diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml
index 123f22b7a3a..83b438d3efc 100644
--- a/hapi-fhir-jpaserver-model/pom.xml
+++ b/hapi-fhir-jpaserver-model/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/BaseHasResource.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/BaseHasResource.java
index 71ad0e10e80..87f33605ee4 100644
--- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/BaseHasResource.java
+++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/BaseHasResource.java
@@ -44,11 +44,6 @@ public abstract class BaseHasResource implements IBaseResourceEntity, IBasePersi
@OptimisticLock(excluded = true)
private FhirVersionEnum myFhirVersion;
- @OneToOne(optional = true, fetch = FetchType.LAZY, cascade = {}, orphanRemoval = false)
- @JoinColumn(name = "FORCED_ID_PID")
- @OptimisticLock(excluded = true)
- private ForcedId myForcedId;
-
@Column(name = "HAS_TAGS", nullable = false)
@OptimisticLock(excluded = true)
private boolean myHasTags;
@@ -106,29 +101,13 @@ public abstract class BaseHasResource implements IBaseResourceEntity, IBasePersi
myFhirVersion = theFhirVersion;
}
- public ForcedId getForcedId() {
- return myForcedId;
- }
+ abstract public ForcedId getForcedId();
- public void setForcedId(ForcedId theForcedId) {
- myForcedId = theForcedId;
- }
+ abstract public void setForcedId(ForcedId theForcedId);
@Override
public abstract Long getId();
- @Override
- public IdDt getIdDt() {
- if (getForcedId() == null) {
- Long id = getResourceId();
- return new IdDt(getResourceType() + '/' + id + '/' + Constants.PARAM_HISTORY + '/' + getVersion());
- } else {
- // Avoid a join query if possible
- String forcedId = getTransientForcedId() != null ? getTransientForcedId() : getForcedId().getForcedId();
- return new IdDt(getResourceType() + '/' + forcedId + '/' + Constants.PARAM_HISTORY + '/' + getVersion());
- }
- }
-
@Override
public boolean isDeleted() {
return myDeleted != null;
diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceHistoryTable.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceHistoryTable.java
index 1e8c84c6c26..fea5496300e 100644
--- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceHistoryTable.java
+++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceHistoryTable.java
@@ -21,6 +21,8 @@ package ca.uhn.fhir.jpa.model.entity;
*/
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
+import ca.uhn.fhir.model.primitive.IdDt;
+import ca.uhn.fhir.rest.api.Constants;
import org.hibernate.annotations.OptimisticLock;
import javax.persistence.*;
@@ -54,7 +56,11 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
@Column(name = "PID")
private Long myId;
- @Column(name = "RES_ID")
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_RESOURCE_HISTORY_RESOURCE"))
+ private ResourceTable myResourceTable;
+
+ @Column(name = "RES_ID", nullable = false, updatable = false, insertable = false)
private Long myResourceId;
@Column(name = "RES_TYPE", length = ResourceTable.RESTYPE_LEN, nullable = false)
@@ -165,4 +171,35 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
public ResourcePersistentId getPersistentId() {
return new ResourcePersistentId(myResourceId);
}
+
+ public ResourceTable getResourceTable() {
+ return myResourceTable;
+ }
+
+ public void setResourceTable(ResourceTable theResourceTable) {
+ myResourceTable = theResourceTable;
+ }
+
+ @Override
+ public IdDt getIdDt() {
+ if (getResourceTable().getForcedId() == null) {
+ Long id = getResourceId();
+ return new IdDt(getResourceType() + '/' + id + '/' + Constants.PARAM_HISTORY + '/' + getVersion());
+ } else {
+ // Avoid a join query if possible
+ String forcedId = getTransientForcedId() != null ? getTransientForcedId() : getResourceTable().getForcedId().getForcedId();
+ return new IdDt(getResourceType() + '/' + forcedId + '/' + Constants.PARAM_HISTORY + '/' + getVersion());
+ }
+ }
+
+ @Override
+ public ForcedId getForcedId() {
+ return getResourceTable().getForcedId();
+ }
+
+ @Override
+ public void setForcedId(ForcedId theForcedId) {
+ getResourceTable().setForcedId(theForcedId);
+ }
+
}
diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceLink.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceLink.java
index 24b9e690b6e..f0ae3b08de3 100644
--- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceLink.java
+++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceLink.java
@@ -84,22 +84,6 @@ public class ResourceLink extends BaseResourceIndex {
super();
}
- public ResourceLink(String theSourcePath, ResourceTable theSourceResource, IIdType theTargetResourceUrl, Date theUpdated) {
- super();
- setSourcePath(theSourcePath);
- setSourceResource(theSourceResource);
- setTargetResourceUrl(theTargetResourceUrl);
- setUpdated(theUpdated);
- }
-
- public ResourceLink(String theSourcePath, ResourceTable theSourceResource, ResourceTable theTargetResource, Date theUpdated) {
- super();
- setSourcePath(theSourcePath);
- setSourceResource(theSourceResource);
- setTargetResource(theTargetResource);
- setUpdated(theUpdated);
- }
-
@Override
public boolean equals(Object theObj) {
if (this == theObj) {
@@ -138,10 +122,6 @@ public class ResourceLink extends BaseResourceIndex {
mySourceResourceType = theSourceResource.getResourceType();
}
- public Long getSourceResourcePid() {
- return mySourceResourcePid;
- }
-
public ResourceTable getTargetResource() {
return myTargetResource;
}
@@ -157,27 +137,30 @@ public class ResourceLink extends BaseResourceIndex {
return myTargetResourcePid;
}
- public String getTargetResourceUrl() {
- return myTargetResourceUrl;
- }
-
public void setTargetResourceUrl(IIdType theTargetResourceUrl) {
Validate.isTrue(theTargetResourceUrl.hasBaseUrl());
Validate.isTrue(theTargetResourceUrl.hasResourceType());
// if (theTargetResourceUrl.hasIdPart()) {
- // do nothing
+ // do nothing
// } else {
- // Must have set an url like http://example.org/something
- // We treat 'something' as the resource type because of fix for #659. Prior to #659 fix, 'something' was
- // treated as the id and 'example.org' was treated as the resource type
- // TODO: log a warning?
+ // Must have set an url like http://example.org/something
+ // We treat 'something' as the resource type because of fix for #659. Prior to #659 fix, 'something' was
+ // treated as the id and 'example.org' was treated as the resource type
+ // TODO: log a warning?
// }
myTargetResourceType = theTargetResourceUrl.getResourceType();
myTargetResourceUrl = theTargetResourceUrl.getValue();
}
+ public void setTargetResourceUrlCanonical(String theTargetResourceUrl) {
+ Validate.notBlank(theTargetResourceUrl);
+
+ myTargetResourceType = "(unknown)";
+ myTargetResourceUrl = theTargetResourceUrl;
+ }
+
public Date getUpdated() {
return myUpdated;
}
@@ -224,4 +207,34 @@ public class ResourceLink extends BaseResourceIndex {
return b.toString();
}
+ public static ResourceLink forAbsoluteReference(String theSourcePath, ResourceTable theSourceResource, IIdType theTargetResourceUrl, Date theUpdated) {
+ ResourceLink retVal = new ResourceLink();
+ retVal.setSourcePath(theSourcePath);
+ retVal.setSourceResource(theSourceResource);
+ retVal.setTargetResourceUrl(theTargetResourceUrl);
+ retVal.setUpdated(theUpdated);
+ return retVal;
+ }
+
+ /**
+ * Factory for canonical URL
+ */
+ public static ResourceLink forLogicalReference(String theSourcePath, ResourceTable theSourceResource, String theTargetResourceUrl, Date theUpdated) {
+ ResourceLink retVal = new ResourceLink();
+ retVal.setSourcePath(theSourcePath);
+ retVal.setSourceResource(theSourceResource);
+ retVal.setTargetResourceUrlCanonical(theTargetResourceUrl);
+ retVal.setUpdated(theUpdated);
+ return retVal;
+ }
+
+ public static ResourceLink forLocalReference(String theSourcePath, ResourceTable theSourceResource, ResourceTable theTargetResource, Date theUpdated) {
+ ResourceLink retVal = new ResourceLink();
+ retVal.setSourcePath(theSourcePath);
+ retVal.setSourceResource(theSourceResource);
+ retVal.setTargetResource(theTargetResource);
+ retVal.setUpdated(theUpdated);
+ return retVal;
+ }
+
}
diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java
index 1fea6e588af..73b5e947c3f 100644
--- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java
+++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java
@@ -23,6 +23,8 @@ package ca.uhn.fhir.jpa.model.entity;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.search.IndexNonDeletedInterceptor;
+import ca.uhn.fhir.model.primitive.IdDt;
+import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@@ -201,26 +203,36 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
@OneToMany(mappedBy = "myTargetResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
@OptimisticLock(excluded = true)
private Collection myResourceLinksAsTarget;
+
@Column(name = "RES_TYPE", length = RESTYPE_LEN, nullable = false)
@Field
@OptimisticLock(excluded = true)
private String myResourceType;
+
@OneToMany(mappedBy = "myResource", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@OptimisticLock(excluded = true)
private Collection mySearchParamPresents;
+
@OneToMany(mappedBy = "myResource", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@OptimisticLock(excluded = true)
private Set myTags;
+
@Transient
private transient boolean myUnchangedInCurrentOperation;
+
@Version
@Column(name = "RES_VER")
private long myVersion;
+
@OneToMany(mappedBy = "myResourceTable", fetch = FetchType.LAZY)
private Collection myProvenance;
+
@Transient
private transient ResourceHistoryTable myCurrentVersionEntity;
+ @OneToOne(optional = true, fetch = FetchType.EAGER, cascade = {}, orphanRemoval = false, mappedBy = "myResource")
+ private ForcedId myForcedId;
+
/**
* Constructor
*/
@@ -558,6 +570,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
retVal.setUpdated(getUpdated());
retVal.setFhirVersion(getFhirVersion());
retVal.setDeleted(getDeleted());
+ retVal.setResourceTable(this);
retVal.setForcedId(getForcedId());
retVal.setTenantId(getTenantId());
@@ -600,20 +613,44 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
* This is a convenience to avoid loading the version a second time within a single transaction. It is
* not persisted.
*/
- public ResourceHistoryTable getCurrentVersionEntity() {
- return myCurrentVersionEntity;
+ public void setCurrentVersionEntity(ResourceHistoryTable theCurrentVersionEntity) {
+ myCurrentVersionEntity = theCurrentVersionEntity;
}
/**
* This is a convenience to avoid loading the version a second time within a single transaction. It is
* not persisted.
*/
- public void setCurrentVersionEntity(ResourceHistoryTable theCurrentVersionEntity) {
- myCurrentVersionEntity = theCurrentVersionEntity;
+ public ResourceHistoryTable getCurrentVersionEntity() {
+ return myCurrentVersionEntity;
}
@Override
public ResourcePersistentId getPersistentId() {
return new ResourcePersistentId(getId());
}
+
+ @Override
+ public ForcedId getForcedId() {
+ return myForcedId;
+ }
+
+ @Override
+ public void setForcedId(ForcedId theForcedId) {
+ myForcedId = theForcedId;
+ }
+
+ @Override
+ public IdDt getIdDt() {
+ if (getForcedId() == null) {
+ Long id = getResourceId();
+ return new IdDt(getResourceType() + '/' + id + '/' + Constants.PARAM_HISTORY + '/' + getVersion());
+ } else {
+ // Avoid a join query if possible
+ String forcedId = getTransientForcedId() != null ? getTransientForcedId() : getForcedId().getForcedId();
+ return new IdDt(getResourceType() + '/' + forcedId + '/' + Constants.PARAM_HISTORY + '/' + getVersion());
+ }
+ }
+
+
}
diff --git a/hapi-fhir-jpaserver-searchparam/pom.xml b/hapi-fhir-jpaserver-searchparam/pom.xml
index 06f462936c4..709f74dfc10 100755
--- a/hapi-fhir-jpaserver-searchparam/pom.xml
+++ b/hapi-fhir-jpaserver-searchparam/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java
index 79bf1c41f4a..10583e7095d 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java
@@ -125,23 +125,29 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
case "uri":
case "canonical":
String typeName = toTypeName(value);
+ IPrimitiveType> valuePrimitive = (IPrimitiveType>) value;
+ IBaseReference fakeReference = (IBaseReference) myContext.getElementDefinition("Reference").newInstance();
+ fakeReference.setReference(valuePrimitive.getValueAsString());
// Canonical has a root type of "uri"
if ("canonical".equals(typeName)) {
- IPrimitiveType> valuePrimitive = (IPrimitiveType>) value;
- IBaseReference fakeReference = (IBaseReference) myContext.getElementDefinition("Reference").newInstance();
- fakeReference.setReference(valuePrimitive.getValueAsString());
/*
* See #1583
* Technically canonical fields should not allow local references (e.g.
* Questionnaire/123) but it seems reasonable for us to interpret a canonical
- * containing a local reference for what it is, and allow people to seaerch
+ * containing a local reference for what it is, and allow people to search
* based on that.
*/
IIdType parsed = fakeReference.getReferenceElement();
if (parsed.hasIdPart() && parsed.hasResourceType() && !parsed.isAbsolute()) {
- PathAndRef ref = new PathAndRef(searchParam.getName(), path, fakeReference);
+ PathAndRef ref = new PathAndRef(searchParam.getName(), path, fakeReference, false);
+ params.add(ref);
+ break;
+ }
+
+ if (parsed.isAbsolute()) {
+ PathAndRef ref = new PathAndRef(searchParam.getName(), path, fakeReference, true);
params.add(ref);
break;
}
@@ -165,7 +171,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
return;
}
- PathAndRef ref = new PathAndRef(searchParam.getName(), path, valueRef);
+ PathAndRef ref = new PathAndRef(searchParam.getName(), path, valueRef, false);
params.add(ref);
break;
default:
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/PathAndRef.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/PathAndRef.java
index 82cb389d15f..22bc6d65b3d 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/PathAndRef.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/PathAndRef.java
@@ -27,15 +27,21 @@ public class PathAndRef {
private final String myPath;
private final IBaseReference myRef;
private final String mySearchParamName;
+ private final boolean myCanonical;
/**
* Constructor
*/
- public PathAndRef(String theSearchParamName, String thePath, IBaseReference theRef) {
+ public PathAndRef(String theSearchParamName, String thePath, IBaseReference theRef, boolean theCanonical) {
super();
mySearchParamName = theSearchParamName;
myPath = thePath;
myRef = theRef;
+ myCanonical = theCanonical;
+ }
+
+ public boolean isCanonical() {
+ return myCanonical;
}
public String getSearchParamName() {
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceLinkExtractor.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceLinkExtractor.java
index dbd8f79f9d9..c496f46e3f5 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceLinkExtractor.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceLinkExtractor.java
@@ -87,8 +87,10 @@ public class ResourceLinkExtractor {
theParams.myPopulatedResourceLinkParameters.add(thePathAndRef.getSearchParamName());
- if (LogicalReferenceHelper.isLogicalReference(myModelConfig, nextId)) {
- ResourceLink resourceLink = new ResourceLink(thePathAndRef.getPath(), theEntity, nextId, theUpdateTime);
+ boolean canonical = thePathAndRef.isCanonical();
+ if (LogicalReferenceHelper.isLogicalReference(myModelConfig, nextId) || canonical) {
+ String value = nextId.getValue();
+ ResourceLink resourceLink = ResourceLink.forLogicalReference(thePathAndRef.getPath(), theEntity, value, theUpdateTime);
if (theParams.myLinks.add(resourceLink)) {
ourLog.debug("Indexing remote resource reference URL: {}", nextId);
}
@@ -130,7 +132,7 @@ public class ResourceLinkExtractor {
String msg = myContext.getLocalizer().getMessage(BaseSearchParamExtractor.class, "externalReferenceNotAllowed", nextId.getValue());
throw new InvalidRequestException(msg);
} else {
- ResourceLink resourceLink = new ResourceLink(thePathAndRef.getPath(), theEntity, nextId, theUpdateTime);
+ ResourceLink resourceLink = ResourceLink.forAbsoluteReference(thePathAndRef.getPath(), theEntity, nextId, theUpdateTime);
if (theParams.myLinks.add(resourceLink)) {
ourLog.debug("Indexing remote resource reference URL: {}", nextId);
}
@@ -165,7 +167,7 @@ public class ResourceLinkExtractor {
return null;
}
- return new ResourceLink(nextPathAndRef.getPath(), theEntity, targetResource, theUpdateTime);
+ return ResourceLink.forLocalReference(nextPathAndRef.getPath(), theEntity, targetResource, theUpdateTime);
}
}
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorR5.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorR5.java
index 9626f14282e..d27f51fc814 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorR5.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorR5.java
@@ -26,12 +26,16 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r5.context.IWorkerContext;
-import org.hl7.fhir.r5.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.r5.hapi.ctx.DefaultProfileValidationSupport;
+import org.hl7.fhir.r5.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.r5.hapi.ctx.IValidationSupport;
-import org.hl7.fhir.r5.model.*;
+import org.hl7.fhir.r5.model.Base;
+import org.hl7.fhir.r5.model.IdType;
+import org.hl7.fhir.r5.model.Resource;
+import org.hl7.fhir.r5.model.ResourceType;
+import org.hl7.fhir.r5.model.TypeDetails;
+import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.FHIRPathEngine;
-import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import java.util.Collections;
@@ -115,7 +119,7 @@ public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements
}
@Override
- public Base resolveReference(Object theAppContext, String theUrl) throws FHIRException {
+ public Base resolveReference(Object appContext, String theUrl, Base refContext) throws FHIRException {
/*
* When we're doing resolution within the SearchParamExtractor, if we want
diff --git a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceIndexedSearchParamsTest.java b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceIndexedSearchParamsTest.java
index 252834ab82c..34032f5c138 100644
--- a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceIndexedSearchParamsTest.java
+++ b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceIndexedSearchParamsTest.java
@@ -32,7 +32,7 @@ public class ResourceIndexedSearchParamsTest {
myTarget.setResourceType("Organization");
myParams = new ResourceIndexedSearchParams(source);
- ResourceLink link = new ResourceLink("organization", source, myTarget, new Date());
+ ResourceLink link = ResourceLink.forLocalReference("organization", source, myTarget, new Date());
myParams.getResourceLinks().add(link);
}
diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml
index 19a6c3caf27..a7e80f6ec98 100644
--- a/hapi-fhir-jpaserver-subscription/pom.xml
+++ b/hapi-fhir-jpaserver-subscription/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelFactory.java
index 2be4dc4d6aa..c2a2eca6589 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelFactory.java
@@ -24,17 +24,11 @@ import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
import ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.SubscribableChannel;
-import org.springframework.stereotype.Component;
-@Component
public class SubscriptionChannelFactory {
- private ISubscribableChannelFactory mySubscribableChannelFactory;
-
@Autowired
- public SubscriptionChannelFactory(ISubscribableChannelFactory theSubscribableChannelFactory) {
- mySubscribableChannelFactory = theSubscribableChannelFactory;
- }
+ private ISubscribableChannelFactory mySubscribableChannelFactory;
public SubscribableChannel newDeliveryChannel(String theChannelName) {
return mySubscribableChannelFactory.createSubscribableChannel(theChannelName, ResourceDeliveryMessage.class, mySubscribableChannelFactory.getDeliveryChannelConcurrentConsumers());
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/config/BaseSubscriptionConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/config/BaseSubscriptionConfig.java
index 8da938d805e..2a45b7a99f5 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/config/BaseSubscriptionConfig.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/config/BaseSubscriptionConfig.java
@@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.subscription.module.config;
import ca.uhn.fhir.interceptor.executor.InterceptorService;
import ca.uhn.fhir.jpa.subscription.module.cache.LinkedBlockingQueueSubscribableChannelFactory;
import ca.uhn.fhir.jpa.subscription.module.channel.ISubscribableChannelFactory;
+import ca.uhn.fhir.jpa.subscription.module.channel.SubscriptionChannelFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@@ -33,7 +34,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@ComponentScan(basePackages = {"ca.uhn.fhir.jpa.subscription.module"})
public abstract class BaseSubscriptionConfig {
@Bean
- public ISubscribableChannelFactory blockingQueueSubscriptionDeliveryChannelFactory() {
+ public ISubscribableChannelFactory subscribableChannelFactory() {
return new LinkedBlockingQueueSubscribableChannelFactory();
}
@@ -41,4 +42,9 @@ public abstract class BaseSubscriptionConfig {
public InterceptorService interceptorRegistry() {
return new InterceptorService("hapi-fhir-jpa-subscription");
}
+
+ @Bean
+ public SubscriptionChannelFactory subscriptionChannelFactory() {
+ return new SubscriptionChannelFactory();
+ }
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientResourceRetriever.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientResourceRetriever.java
index 2a4f5ba24ab..d112209ae2d 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientResourceRetriever.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientResourceRetriever.java
@@ -45,6 +45,6 @@ public class FhirClientResourceRetriever implements IResourceRetriever {
public IBaseResource getResource(IIdType payloadId) throws ResourceGoneException {
RuntimeResourceDefinition resourceDef = myFhirContext.getResourceDefinition(payloadId.getResourceType());
- return myClient.search().forResource(resourceDef.getName()).withIdAndCompartment(payloadId.getIdPart(), payloadId.getResourceType()).execute();
+ return myClient.read().resource(resourceDef.getName()).withId(payloadId).execute();
}
}
diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml
index 32f3752d80e..e6234a4fec8 100644
--- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml
+++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../pom.xml
@@ -157,7 +157,7 @@
ca.uhn.hapi.fhir
hapi-fhir-converter
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml
index 56d24a8322d..7e17a896660 100644
--- a/hapi-fhir-server/pom.xml
+++ b/hapi-fhir-server/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/ReadMethodBinding.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/ReadMethodBinding.java
index 935b0c62703..facae61707d 100644
--- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/ReadMethodBinding.java
+++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/method/ReadMethodBinding.java
@@ -160,7 +160,7 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding {
IBundleProvider retVal = toResourceList(response);
- if (retVal.size() == 1) {
+ if (Integer.valueOf(1).equals(retVal.size())) {
List responseResources = retVal.getResources(0, 1);
IBaseResource responseResource = responseResources.get(0);
diff --git a/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/method/ReadMethodBindingTest.java b/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/method/ReadMethodBindingTest.java
index 598dddf84aa..ba4ee6476ce 100644
--- a/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/method/ReadMethodBindingTest.java
+++ b/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/method/ReadMethodBindingTest.java
@@ -59,6 +59,11 @@ public class ReadMethodBindingTest {
assertTrue(binding.incomingServerRequestMatchesMethod(myRequestDetails));
// VRead
+ when(myRequestDetails.getId()).thenReturn(new IdDt("Patient/123/_history/123"));
+ assertFalse(binding.incomingServerRequestMatchesMethod(myRequestDetails));
+
+ // Type history
+ when(myRequestDetails.getId()).thenReturn(new IdDt("Patient/123"));
when(myRequestDetails.getResourceName()).thenReturn("Patient");
when(myRequestDetails.getOperation()).thenReturn("_history");
assertFalse(binding.incomingServerRequestMatchesMethod(myRequestDetails));
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml
index e6f6a6546cd..834ad669a7d 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml
index 6460fdaa090..31805755c96 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot-samples
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
hapi-fhir-spring-boot-sample-client-apache
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml
index ec9c4c7b647..1d4b77cb9f0 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot-samples
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
hapi-fhir-spring-boot-sample-client-okhttp
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml
index 45d11f2b0a0..09556aa2e9d 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot-samples
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
hapi-fhir-spring-boot-sample-server-jersey
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jpa/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jpa/pom.xml
index 2f99de20e6b..a087c508c21 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jpa/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jpa/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot-samples
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
hapi-fhir-spring-boot-sample-server-jpa
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml
index bdeeb2a13a3..5b9868d5d9c 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
hapi-fhir-spring-boot-samples
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml
index 95bbb629d7f..4869dd92e80 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml
index 83dcdd267d7..1b15296e40b 100644
--- a/hapi-fhir-spring-boot/pom.xml
+++ b/hapi-fhir-spring-boot/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml
index c12b498af04..2e2a8777742 100644
--- a/hapi-fhir-structures-dstu2.1/pom.xml
+++ b/hapi-fhir-structures-dstu2.1/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml
index cb64e29ef8d..48444b154a0 100644
--- a/hapi-fhir-structures-dstu2/pom.xml
+++ b/hapi-fhir-structures-dstu2/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml
index e8955655dd3..f8d1d20457a 100644
--- a/hapi-fhir-structures-dstu3/pom.xml
+++ b/hapi-fhir-structures-dstu3/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/ctx/HapiWorkerContext.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/ctx/HapiWorkerContext.java
index cf67693767e..84e62466d92 100644
--- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/ctx/HapiWorkerContext.java
+++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/ctx/HapiWorkerContext.java
@@ -106,14 +106,22 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander
@Override
public T fetchResource(Class theClass, String theUri) {
+ Validate.notBlank(theUri, "theUri must not be null or blank");
if (myValidationSupport == null) {
return null;
} else {
- @SuppressWarnings("unchecked")
- T retVal = (T) myFetchedResourceCache.get(theUri, t->{
- return myValidationSupport.fetchResource(myCtx, theClass, theUri);
- });
- return retVal;
+ try {
+ //noinspection unchecked
+ return (T) myFetchedResourceCache.get(theUri, t -> {
+ T resource = myValidationSupport.fetchResource(myCtx, theClass, theUri);
+ if (resource == null) {
+ throw new IllegalArgumentException();
+ }
+ return resource;
+ });
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
}
}
diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml
index f92fd6871e2..ab9eb4e3214 100644
--- a/hapi-fhir-structures-hl7org-dstu2/pom.xml
+++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml
index e4e51da7cfa..cdea8e99b14 100644
--- a/hapi-fhir-structures-r4/pom.xml
+++ b/hapi-fhir-structures-r4/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/context/BaseRuntimeElementDefinitionTest.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/context/BaseRuntimeElementDefinitionTest.java
new file mode 100644
index 00000000000..965a327ef3a
--- /dev/null
+++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/context/BaseRuntimeElementDefinitionTest.java
@@ -0,0 +1,23 @@
+package ca.uhn.fhir.context;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class BaseRuntimeElementDefinitionTest {
+
+ @Test
+ public void testNewInstance_InvalidArgumentType() {
+ FhirContext ctx = FhirContext.forR4();
+
+ BaseRuntimeElementDefinition> def = ctx.getElementDefinition("string");
+
+ try {
+ def.newInstance(123);
+ fail();
+ } catch (ConfigurationException e) {
+ assertEquals("Failed to instantiate type:org.hl7.fhir.r4.model.StringType", e.getMessage());
+ }
+ }
+
+}
diff --git a/hapi-fhir-structures-r5/pom.xml b/hapi-fhir-structures-r5/pom.xml
index 92dabe9671b..ffd8da62120 100644
--- a/hapi-fhir-structures-r5/pom.xml
+++ b/hapi-fhir-structures-r5/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java b/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java
index c48a81f8f5e..c88ada2d294 100644
--- a/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java
+++ b/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java
@@ -343,6 +343,11 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander
return fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + typeName);
}
+ @Override
+ public StructureDefinition fetchRawProfile(String url) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public List getTypeNames() {
throw new UnsupportedOperationException();
diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml
index d010e06b048..6caefd3117b 100644
--- a/hapi-fhir-test-utilities/pom.xml
+++ b/hapi-fhir-test-utilities/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
@@ -19,17 +19,17 @@
ca.uhn.hapi.fhir
hapi-fhir-base
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-server
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-client
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java b/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java
index 0c95bca015b..7d9b94b7ed8 100644
--- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java
+++ b/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java
@@ -51,6 +51,7 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
private int myDefaultTimeoutSeconds = DEFAULT_TIMEOUT_SECONDS;
private final Pointcut myPointcut;
private int myInitialCount;
+ private boolean myExactMatch;
public PointcutLatch(Pointcut thePointcut) {
@@ -69,19 +70,32 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
}
@Override
- public void setExpectedCount(int count) {
+ public void setExpectedCount(int theCount) {
+ this.setExpectedCount(theCount, true);
+ }
+
+ public void setExpectedCount(int theCount, boolean theExactMatch) {
if (myCountdownLatch.get() != null) {
throw new PointcutLatchException("setExpectedCount() called before previous awaitExpected() completed.");
}
- createLatch(count);
- ourLog.info("Expecting {} calls to {} latch", count, name);
+ myExactMatch = theExactMatch;
+ createLatch(theCount);
+ if (theExactMatch) {
+ ourLog.info("Expecting exactly {} calls to {} latch", theCount, name);
+ } else {
+ ourLog.info("Expecting at least {} calls to {} latch", theCount, name);
+ }
}
- private void createLatch(int count) {
+ public void setExpectAtLeast(int theCount) {
+ setExpectedCount(theCount, false);
+ }
+
+ private void createLatch(int theCount) {
myFailures.set(Collections.synchronizedList(new ArrayList<>()));
myCalledWith.set(Collections.synchronizedList(new ArrayList<>()));
- myCountdownLatch.set(new CountDownLatch(count));
- myInitialCount = count;
+ myCountdownLatch.set(new CountDownLatch(theCount));
+ myInitialCount = theCount;
}
private void addFailure(String failure) {
@@ -153,10 +167,14 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
@Override
public void invoke(Pointcut thePointcut, HookParams theArgs) {
CountDownLatch latch = myCountdownLatch.get();
- if (latch == null) {
- throw new PointcutLatchException("invoke() called outside of setExpectedCount() .. awaitExpected(). Probably got more invocations than expected or clear() was called before invoke() arrived.", theArgs);
- } else if (latch.getCount() <= 0) {
- addFailure("invoke() called when countdown was zero.");
+ if (myExactMatch) {
+ if (latch == null) {
+ throw new PointcutLatchException("invoke() called outside of setExpectedCount() .. awaitExpected(). Probably got more invocations than expected or clear() was called before invoke() arrived.", theArgs);
+ } else if (latch.getCount() <= 0) {
+ addFailure("invoke() called when countdown was zero.");
+ }
+ } else if (latch == null || latch.getCount() <= 0) {
+ return;
}
if (myCalledWith.get() != null) {
diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml
index b8bca0e0dad..107e75d8313 100644
--- a/hapi-fhir-testpage-overlay/pom.xml
+++ b/hapi-fhir-testpage-overlay/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml
index ad05fd25d1a..c4bae7d6848 100644
--- a/hapi-fhir-validation-resources-dstu2.1/pom.xml
+++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml
index 45aa002c077..d8b4b070e80 100644
--- a/hapi-fhir-validation-resources-dstu2/pom.xml
+++ b/hapi-fhir-validation-resources-dstu2/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml
index 566d901943a..152a124fc68 100644
--- a/hapi-fhir-validation-resources-dstu3/pom.xml
+++ b/hapi-fhir-validation-resources-dstu3/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml
index e0284321e23..901d583f414 100644
--- a/hapi-fhir-validation-resources-r4/pom.xml
+++ b/hapi-fhir-validation-resources-r4/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-r5/pom.xml b/hapi-fhir-validation-resources-r5/pom.xml
index afa97d77f1c..708cbe421a7 100644
--- a/hapi-fhir-validation-resources-r5/pom.xml
+++ b/hapi-fhir-validation-resources-r5/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml
index 751a3b721ee..9a7e1c13971 100644
--- a/hapi-fhir-validation/pom.xml
+++ b/hapi-fhir-validation/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/ValidatorWrapper.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/ValidatorWrapper.java
index d1c28f2b274..717279b54c1 100644
--- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/ValidatorWrapper.java
+++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/ValidatorWrapper.java
@@ -4,20 +4,24 @@ import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.util.XmlUtil;
import ca.uhn.fhir.validation.IValidationContext;
-import com.google.gson.*;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
import org.apache.commons.codec.Charsets;
import org.apache.commons.io.input.ReaderInputStream;
+import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.elementmodel.Manager;
+import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.utils.FHIRPathEngine;
import org.hl7.fhir.r5.utils.IResourceValidator;
-import org.hl7.fhir.r5.utils.ValidationProfileSet;
import org.hl7.fhir.r5.validation.InstanceValidator;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.io.InputStream;
@@ -33,7 +37,9 @@ public class ValidatorWrapper {
private boolean myAnyExtensionsAllowed;
private boolean myErrorForUnknownProfiles;
private boolean myNoTerminologyChecks;
+ private boolean myAssumeValidRestReferences;
private Collection extends String> myExtensionDomains;
+ private IResourceValidator.IValidatorResourceFetcher myValidatorResourceFetcher;
/**
* Constructor
@@ -42,6 +48,15 @@ public class ValidatorWrapper {
super();
}
+ public boolean isAssumeValidRestReferences() {
+ return myAssumeValidRestReferences;
+ }
+
+ public ValidatorWrapper setAssumeValidRestReferences(boolean assumeValidRestReferences) {
+ this.myAssumeValidRestReferences = assumeValidRestReferences;
+ return this;
+ }
+
public ValidatorWrapper setBestPracticeWarningLevel(IResourceValidator.BestPracticeWarningLevel theBestPracticeWarningLevel) {
myBestPracticeWarningLevel = theBestPracticeWarningLevel;
return this;
@@ -67,6 +82,12 @@ public class ValidatorWrapper {
return this;
}
+
+ public ValidatorWrapper setValidatorResourceFetcher(IResourceValidator.IValidatorResourceFetcher validatorResourceFetcher) {
+ this.myValidatorResourceFetcher = validatorResourceFetcher;
+ return this;
+ }
+
public List validate(IWorkerContext theWorkerContext, IValidationContext> theValidationContext) {
InstanceValidator v;
FHIRPathEngine.IEvaluationContext evaluationCtx = new org.hl7.fhir.r5.hapi.validation.FhirInstanceValidator.NullEvaluationContext();
@@ -76,19 +97,21 @@ public class ValidatorWrapper {
throw new ConfigurationException(e);
}
+ v.setAssumeValidRestReferences(isAssumeValidRestReferences());
v.setBestPracticeWarningLevel(myBestPracticeWarningLevel);
v.setAnyExtensionsAllowed(myAnyExtensionsAllowed);
v.setResourceIdRule(IResourceValidator.IdStatus.OPTIONAL);
v.setNoTerminologyChecks(myNoTerminologyChecks);
v.setErrorForUnknownProfiles(myErrorForUnknownProfiles);
v.getExtensionDomains().addAll(myExtensionDomains);
+ v.setFetcher(myValidatorResourceFetcher);
v.setAllowXsiLocation(true);
List messages = new ArrayList<>();
- ValidationProfileSet profileSet = new ValidationProfileSet();
+ List profileUrls = new ArrayList<>();
for (String next : theValidationContext.getOptions().getProfiles()) {
- profileSet.getCanonical().add(new ValidationProfileSet.ProfileRegistration(next, true));
+ fetchAndAddProfile(theWorkerContext, profileUrls, next);
}
String input = theValidationContext.getResourceAsString();
@@ -109,14 +132,14 @@ public class ValidatorWrapper {
// Determine if meta/profiles are present...
ArrayList profiles = determineIfProfilesSpecified(document);
for (String nextProfile : profiles) {
- profileSet.getCanonical().add(new ValidationProfileSet.ProfileRegistration(nextProfile, true));
+ fetchAndAddProfile(theWorkerContext, profileUrls, nextProfile);
}
String resourceAsString = theValidationContext.getResourceAsString();
InputStream inputStream = new ReaderInputStream(new StringReader(resourceAsString), Charsets.UTF_8);
Manager.FhirFormat format = Manager.FhirFormat.XML;
- v.validate(null, messages, inputStream, format, profileSet);
+ v.validate(null, messages, inputStream, format, profileUrls);
} else if (encoding == EncodingEnum.JSON) {
@@ -129,7 +152,8 @@ public class ValidatorWrapper {
if (profileElement != null && profileElement.isJsonArray()) {
JsonArray profiles = profileElement.getAsJsonArray();
for (JsonElement element : profiles) {
- profileSet.getCanonical().add(new ValidationProfileSet.ProfileRegistration(element.getAsString(), true));
+ String nextProfile = element.getAsString();
+ fetchAndAddProfile(theWorkerContext, profileUrls, nextProfile);
}
}
}
@@ -138,7 +162,7 @@ public class ValidatorWrapper {
InputStream inputStream = new ReaderInputStream(new StringReader(resourceAsString), Charsets.UTF_8);
Manager.FhirFormat format = Manager.FhirFormat.JSON;
- v.validate(null, messages, inputStream, format, profileSet);
+ v.validate(null, messages, inputStream, format, profileUrls);
} else {
throw new IllegalArgumentException("Unknown encoding: " + encoding);
@@ -147,27 +171,33 @@ public class ValidatorWrapper {
for (int i = 0; i < messages.size(); i++) {
ValidationMessage next = messages.get(i);
String message = next.getMessage();
+
+ // TODO: are these still needed?
if ("Binding has no source, so can't be checked".equals(message) ||
"ValueSet http://hl7.org/fhir/ValueSet/mimetypes not found".equals(message)) {
messages.remove(i);
i--;
}
+
+ if (message.endsWith("' could not be resolved, so has not been checked") && next.getLevel() == ValidationMessage.IssueSeverity.WARNING) {
+ next.setLevel(ValidationMessage.IssueSeverity.ERROR);
+ }
+
}
return messages;
}
-
- private String determineResourceName(Document theDocument) {
- NodeList list = theDocument.getChildNodes();
- for (int i = 0; i < list.getLength(); i++) {
- if (list.item(i) instanceof Element) {
- return list.item(i).getLocalName();
- }
+ private void fetchAndAddProfile(IWorkerContext theWorkerContext, List theProfileStructureDefinitions, String theUrl) throws org.hl7.fhir.exceptions.FHIRException {
+ try {
+ StructureDefinition structureDefinition = theWorkerContext.fetchResourceWithException(StructureDefinition.class, theUrl);
+ theProfileStructureDefinitions.add(structureDefinition);
+ } catch (FHIRException e) {
+ ourLog.debug("Failed to load profile: {}", theUrl);
}
- return theDocument.getDocumentElement().getLocalName();
}
+
private ArrayList determineIfProfilesSpecified(Document theDocument) {
ArrayList profileNames = new ArrayList<>();
NodeList list = theDocument.getChildNodes().item(0).getChildNodes();
diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/FhirInstanceValidator.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/FhirInstanceValidator.java
index e583381a5ee..e4ab01d7f78 100644
--- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/FhirInstanceValidator.java
+++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/FhirInstanceValidator.java
@@ -1,14 +1,10 @@
package org.hl7.fhir.dstu2016may.hapi.validation;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
+import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.Constants;
+import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
+import ca.uhn.fhir.validation.IValidationContext;
+import ca.uhn.fhir.validation.IValidatorModule;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import org.apache.commons.lang3.Validate;
@@ -18,28 +14,45 @@ import org.apache.commons.lang3.time.DateUtils;
import org.fhir.ucum.UcumService;
import org.hl7.fhir.common.hapi.validation.ValidatorWrapper;
import org.hl7.fhir.convertors.VersionConvertor_14_50;
+import org.hl7.fhir.convertors.conv14_50.CodeSystem14_50;
+import org.hl7.fhir.convertors.conv14_50.StructureDefinition14_50;
+import org.hl7.fhir.convertors.conv14_50.ValueSet14_50;
+import org.hl7.fhir.dstu2016may.model.CodeSystem;
+import org.hl7.fhir.dstu2016may.model.CodeableConcept;
+import org.hl7.fhir.dstu2016may.model.Coding;
+import org.hl7.fhir.dstu2016may.model.ImplementationGuide;
+import org.hl7.fhir.dstu2016may.model.Questionnaire;
+import org.hl7.fhir.dstu2016may.model.StructureDefinition;
+import org.hl7.fhir.dstu2016may.model.ValueSet;
import org.hl7.fhir.exceptions.DefinitionException;
+import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.formats.IParser;
import org.hl7.fhir.r5.formats.ParserType;
import org.hl7.fhir.r5.model.CanonicalResource;
+import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.utils.INarrativeGenerator;
import org.hl7.fhir.r5.utils.IResourceValidator;
-import org.hl7.fhir.r5.model.Resource;
-import org.hl7.fhir.dstu2016may.model.*;
-import org.hl7.fhir.exceptions.FHIRException;
-import org.hl7.fhir.utilities.TerminologyServiceOptions;
import org.hl7.fhir.utilities.TranslationServices;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationOptions;
-import org.w3c.dom.*;
+import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
-import ca.uhn.fhir.validation.IValidationContext;
-import ca.uhn.fhir.validation.IValidatorModule;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
public class FhirInstanceValidator extends BaseValidatorBridge implements IValidatorModule {
@@ -382,7 +395,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
}
public org.hl7.fhir.r5.model.StructureDefinition convert(StructureDefinition next) {
- org.hl7.fhir.r5.model.StructureDefinition structureDefinition = VersionConvertor_14_50.convertStructureDefinition(next);
+ org.hl7.fhir.r5.model.StructureDefinition structureDefinition = StructureDefinition14_50.convertStructureDefinition(next);
if (next.getDerivation() != org.hl7.fhir.dstu2016may.model.StructureDefinition.TypeDerivationRule.CONSTRAINT) {
structureDefinition.setType(next.getName());
}
@@ -408,7 +421,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent conceptDefinition = null;
if (theResult.asConceptDefinition() != null) {
try {
- conceptDefinition = VersionConvertor_14_50.convertConceptDefinitionComponent(theResult.asConceptDefinition());
+ conceptDefinition = CodeSystem14_50.convertConceptDefinitionComponent(theResult.asConceptDefinition());
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -428,7 +441,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
public org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome expandVS(org.hl7.fhir.r5.model.ValueSet source, boolean cacheOk, boolean heiarchical) {
ValueSet convertedSource;
try {
- convertedSource = VersionConvertor_14_50.convertValueSet(source);
+ convertedSource = ValueSet14_50.convertValueSet(source);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -437,7 +450,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
org.hl7.fhir.r5.model.ValueSet convertedResult = null;
if (expanded.getValueset() != null) {
try {
- convertedResult = VersionConvertor_14_50.convertValueSet(expanded.getValueset());
+ convertedResult = ValueSet14_50.convertValueSet(expanded.getValueset());
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -458,7 +471,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
ValueSet.ConceptSetComponent convertedInc = null;
if (inc != null) {
try {
- convertedInc = VersionConvertor_14_50.convertConceptSetComponent(inc);
+ convertedInc = ValueSet14_50.convertConceptSetComponent(inc);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -468,7 +481,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent valueSetExpansionComponent = null;
if (expansion != null) {
try {
- valueSetExpansionComponent = VersionConvertor_14_50.convertValueSetExpansionComponent(expansion);
+ valueSetExpansionComponent = ValueSet14_50.convertValueSetExpansionComponent(expansion);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -492,7 +505,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
return null;
}
try {
- return VersionConvertor_14_50.convertCodeSystem(fetched);
+ return CodeSystem14_50.convertCodeSystem(fetched);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -572,6 +585,11 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
return fetchResource(org.hl7.fhir.r5.model.StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + typeName);
}
+ @Override
+ public org.hl7.fhir.r5.model.StructureDefinition fetchRawProfile(String url) {
+ return fetchResource(org.hl7.fhir.r5.model.StructureDefinition.class, url);
+ }
+
@Override
public List getTypeNames() {
@@ -665,7 +683,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
try {
if (vs != null) {
- convertedVs = VersionConvertor_14_50.convertValueSet(vs);
+ convertedVs = ValueSet14_50.convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -680,7 +698,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
ValueSet convertedVs = null;
try {
if (vs != null) {
- convertedVs = VersionConvertor_14_50.convertValueSet(vs);
+ convertedVs = ValueSet14_50.convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -700,7 +718,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
convertedCode = VersionConvertor_14_50.convertCoding(code);
}
if (vs != null) {
- convertedVs = VersionConvertor_14_50.convertValueSet(vs);
+ convertedVs = ValueSet14_50.convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -720,7 +738,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
convertedCode = VersionConvertor_14_50.convertCodeableConcept(code);
}
if (vs != null) {
- convertedVs = VersionConvertor_14_50.convertValueSet(vs);
+ convertedVs = ValueSet14_50.convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidator.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidator.java
index ba3c7a8755f..609941ba6a9 100644
--- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidator.java
+++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidator.java
@@ -23,6 +23,7 @@ import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.ImplementationGuide;
import org.hl7.fhir.dstu3.model.Questionnaire;
import org.hl7.fhir.dstu3.model.Resource;
+import org.hl7.fhir.dstu3.model.SearchParameter;
import org.hl7.fhir.dstu3.model.StructureDefinition;
import org.hl7.fhir.dstu3.model.ValueSet;
import org.hl7.fhir.exceptions.FHIRException;
@@ -56,6 +57,13 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
+import static org.hl7.fhir.convertors.conv30_50.CodeSystem30_50.convertCodeSystem;
+import static org.hl7.fhir.convertors.conv30_50.CodeSystem30_50.convertConceptDefinitionComponent;
+import static org.hl7.fhir.convertors.conv30_50.StructureDefinition30_50.convertStructureDefinition;
+import static org.hl7.fhir.convertors.conv30_50.ValueSet30_50.convertConceptSetComponent;
+import static org.hl7.fhir.convertors.conv30_50.ValueSet30_50.convertValueSet;
+import static org.hl7.fhir.convertors.conv30_50.ValueSet30_50.convertValueSetExpansionComponent;
+
@SuppressWarnings({"PackageAccessibility", "Duplicates"})
public class FhirInstanceValidator extends BaseValidatorBridge implements IInstanceValidatorModule {
@@ -66,10 +74,12 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
private StructureDefinition myStructureDefintion;
private IValidationSupport myValidationSupport;
private boolean noTerminologyChecks = false;
+ private IResourceValidator.IValidatorResourceFetcher validatorResourceFetcher;
private volatile WorkerContextWrapper myWrappedWorkerContext;
private boolean errorForUnknownProfiles;
private List myExtensionDomains = Collections.emptyList();
+ private boolean assumeValidRestReferences;
/**
* Constructor
@@ -285,10 +295,28 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
.setErrorForUnknownProfiles(isErrorForUnknownProfiles())
.setExtensionDomains(getExtensionDomains())
.setNoTerminologyChecks(isNoTerminologyChecks())
+ .setValidatorResourceFetcher(getValidatorResourceFetcher())
+ .setAssumeValidRestReferences(isAssumeValidRestReferences())
.validate(wrappedWorkerContext, theValidationCtx);
}
+ public IResourceValidator.IValidatorResourceFetcher getValidatorResourceFetcher() {
+ return validatorResourceFetcher;
+ }
+
+ public void setValidatorResourceFetcher(IResourceValidator.IValidatorResourceFetcher validatorResourceFetcher) {
+ this.validatorResourceFetcher = validatorResourceFetcher;
+ }
+
+ public boolean isAssumeValidRestReferences() {
+ return assumeValidRestReferences;
+ }
+
+ public void setAssumeValidRestReferences(boolean assumeValidRestReferences) {
+ this.assumeValidRestReferences = assumeValidRestReferences;
+ }
+
private static class WorkerContextWrapper implements IWorkerContext {
private final HapiWorkerContext myWrap;
@@ -327,6 +355,9 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
case "ImplementationGuide":
fetched = myWrap.fetchResource(ImplementationGuide.class, key.getUri());
break;
+ case "SearchParameter":
+ fetched = myWrap.fetchResource(SearchParameter.class, key.getUri());
+ break;
default:
throw new UnsupportedOperationException("Don't know how to fetch " + key.getResourceName());
}
@@ -386,7 +417,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
retVal = new ArrayList<>();
for (StructureDefinition next : myWrap.allStructures()) {
try {
- retVal.add(VersionConvertor_30_50.convertStructureDefinition(next));
+ retVal.add(convertStructureDefinition(next));
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -416,7 +447,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent conceptDefinition = null;
if (theResult.asConceptDefinition() != null) {
try {
- conceptDefinition = VersionConvertor_30_50.convertConceptDefinitionComponent(theResult.asConceptDefinition());
+ conceptDefinition = convertConceptDefinitionComponent(theResult.asConceptDefinition());
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -436,7 +467,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
public ValueSetExpander.ValueSetExpansionOutcome expandVS(org.hl7.fhir.r5.model.ValueSet source, boolean cacheOk, boolean heiarchical) {
ValueSet convertedSource;
try {
- convertedSource = VersionConvertor_30_50.convertValueSet(source);
+ convertedSource = convertValueSet(source);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -445,7 +476,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
org.hl7.fhir.r5.model.ValueSet convertedResult = null;
if (expanded.getValueset() != null) {
try {
- convertedResult = VersionConvertor_30_50.convertValueSet(expanded.getValueset());
+ convertedResult = convertValueSet(expanded.getValueset());
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -467,7 +498,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
ValueSet.ConceptSetComponent convertedInc = null;
if (inc != null) {
try {
- convertedInc = VersionConvertor_30_50.convertConceptSetComponent(inc);
+ convertedInc = convertConceptSetComponent(inc);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -477,7 +508,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent valueSetExpansionComponent = null;
if (expansion != null) {
try {
- valueSetExpansionComponent = VersionConvertor_30_50.convertValueSetExpansionComponent(expansion);
+ valueSetExpansionComponent = convertValueSetExpansionComponent(expansion);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -495,7 +526,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
return null;
}
try {
- return VersionConvertor_30_50.convertCodeSystem(fetched);
+ return convertCodeSystem(fetched);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -584,6 +615,11 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
return fetchResource(org.hl7.fhir.r5.model.StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + typeName);
}
+ @Override
+ public org.hl7.fhir.r5.model.StructureDefinition fetchRawProfile(String url) {
+ return fetchResource(org.hl7.fhir.r5.model.StructureDefinition.class, url);
+ }
+
@Override
public List getTypeNames() {
return myWrap.getTypeNames();
@@ -676,7 +712,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
try {
if (vs != null) {
- convertedVs = VersionConvertor_30_50.convertValueSet(vs);
+ convertedVs = convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -691,7 +727,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
ValueSet convertedVs = null;
try {
if (vs != null) {
- convertedVs = VersionConvertor_30_50.convertValueSet(vs);
+ convertedVs = convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -711,7 +747,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
convertedCode = VersionConvertor_30_50.convertCoding(code);
}
if (vs != null) {
- convertedVs = VersionConvertor_30_50.convertValueSet(vs);
+ convertedVs = convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -731,7 +767,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
convertedCode = VersionConvertor_30_50.convertCodeableConcept(code);
}
if (vs != null) {
- convertedVs = VersionConvertor_30_50.convertValueSet(vs);
+ convertedVs = convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/FhirInstanceValidator.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/FhirInstanceValidator.java
index a92e2a957af..877c9cfa880 100644
--- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/FhirInstanceValidator.java
+++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/FhirInstanceValidator.java
@@ -27,12 +27,13 @@ import org.fhir.ucum.UcumService;
import org.hl7.fhir.converter.NullVersionConverterAdvisor50;
import org.hl7.fhir.convertors.VersionConvertorAdvisor50;
import org.hl7.fhir.convertors.VersionConvertor_10_50;
+import org.hl7.fhir.convertors.conv10_50.ValueSet10_50;
+import org.hl7.fhir.convertors.conv14_50.CodeSystem14_50;
import org.hl7.fhir.dstu2.model.CodeableConcept;
import org.hl7.fhir.dstu2.model.Coding;
import org.hl7.fhir.dstu2.model.Questionnaire;
import org.hl7.fhir.dstu2.model.StructureDefinition;
import org.hl7.fhir.dstu2.model.ValueSet;
-import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.context.IWorkerContext;
@@ -60,6 +61,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -69,6 +71,11 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import static org.apache.commons.lang3.StringUtils.isBlank;
+import static org.hl7.fhir.convertors.VersionConvertor_10_50.convertCoding;
+import static org.hl7.fhir.convertors.conv10_50.StructureDefinition10_50.convertStructureDefinition;
+import static org.hl7.fhir.convertors.conv10_50.ValueSet10_50.convertConceptSetComponent;
+import static org.hl7.fhir.convertors.conv10_50.ValueSet10_50.convertValueSet;
+import static org.hl7.fhir.convertors.conv10_50.ValueSet10_50.convertValueSetExpansionComponent;
public class FhirInstanceValidator extends BaseValidatorBridge implements IInstanceValidatorModule {
@@ -81,8 +88,19 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
private StructureDefinition myStructureDefintion;
private IValidationSupport myValidationSupport;
private boolean noTerminologyChecks = false;
+
+ public boolean isAssumeValidRestReferences() {
+ return assumeValidRestReferences;
+ }
+
+ public void setAssumeValidRestReferences(boolean assumeValidRestReferences) {
+ this.assumeValidRestReferences = assumeValidRestReferences;
+ }
+
+ private boolean assumeValidRestReferences;
private volatile WorkerContextWrapper myWrappedWorkerContext;
private VersionConvertorAdvisor50 myAdvisor = new NullVersionConverterAdvisor50();
+ private IResourceValidator.IValidatorResourceFetcher validatorResourceFetcher;
/**
* Constructor
@@ -287,6 +305,8 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
v.setAnyExtensionsAllowed(isAnyExtensionsAllowed());
v.setResourceIdRule(IdStatus.OPTIONAL);
v.setNoTerminologyChecks(isNoTerminologyChecks());
+ v.setFetcher(getValidatorResourceFetcher());
+ v.setAssumeValidRestReferences(isAssumeValidRestReferences());
List messages = new ArrayList<>();
@@ -388,6 +408,14 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
return messages;
}
+ public IResourceValidator.IValidatorResourceFetcher getValidatorResourceFetcher() {
+ return validatorResourceFetcher;
+ }
+
+ public void setValidatorResourceFetcher(IResourceValidator.IValidatorResourceFetcher validatorResourceFetcher) {
+ this.validatorResourceFetcher = validatorResourceFetcher;
+ }
+
@Override
protected List validate(IValidationContext> theCtx) {
return validate(theCtx.getFhirContext(), theCtx.getResourceAsString(), theCtx.getResourceAsStringEncoding());
@@ -428,7 +456,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
return null;
}
}
- profileText = IOUtils.toString(inputStream, "UTF-8");
+ profileText = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
} catch (IOException e1) {
if (theMessages != null) {
theMessages.add(new ValidationMessage().setLevel(IssueSeverity.FATAL)
@@ -457,11 +485,17 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
case "StructureDefinition":
fetched = myWrap.fetchResource(StructureDefinition.class, key.getUri());
break;
+ case "CodeSystem":
case "ValueSet":
fetched = myWrap.fetchResource(ValueSet.class, key.getUri());
- break;
- case "CodeSystem":
- fetched = myWrap.fetchResource(ValueSet.class, key.getUri());
+
+ ValueSet fetchedVs = (ValueSet) fetched;
+ if (!fetchedVs.hasCompose()) {
+ if (fetchedVs.hasCodeSystem()) {
+ fetchedVs.getCompose().addInclude().setSystem(fetchedVs.getCodeSystem().getSystem());
+ }
+ }
+
break;
case "Questionnaire":
fetched = myWrap.fetchResource(Questionnaire.class, key.getUri());
@@ -477,7 +511,15 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
}
try {
- org.hl7.fhir.r5.model.Resource converted = new VersionConvertor_10_50(myAdvisor).convertResource(fetched);
+ org.hl7.fhir.r5.model.Resource converted;
+ if ("CodeSystem".equals(key.getUri())) {
+ NullVersionConverterAdvisor50 advisor = new NullVersionConverterAdvisor50();
+ converted = ValueSet10_50.convertValueSet((ValueSet) fetched, advisor);
+ converted = advisor.getCodeSystem((org.hl7.fhir.r5.model.ValueSet) converted);
+ } else {
+ converted = VersionConvertor_10_50.convertResource(fetched);
+ }
+
if (fetched instanceof StructureDefinition) {
StructureDefinition fetchedSd = (StructureDefinition) fetched;
@@ -501,7 +543,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
public WorkerContextWrapper(HapiWorkerContext theWorkerContext) {
myWrap = theWorkerContext;
- myConverter = new VersionConvertor_10_50(myAdvisor);
+ myConverter = new VersionConvertor_10_50();
}
@Override
@@ -510,7 +552,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
}
@Override
- public void generateSnapshot(org.hl7.fhir.r5.model.StructureDefinition p) throws DefinitionException, FHIRException {
+ public void generateSnapshot(org.hl7.fhir.r5.model.StructureDefinition p) throws FHIRException {
}
@@ -547,7 +589,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
retVal = new ArrayList<>();
for (StructureDefinition next : myWrap.allStructures()) {
try {
- org.hl7.fhir.r5.model.StructureDefinition converted = new VersionConvertor_10_50(myAdvisor).convertStructureDefinition(next);
+ org.hl7.fhir.r5.model.StructureDefinition converted = convertStructureDefinition(next);
if (converted != null) {
retVal.add(converted);
}
@@ -587,7 +629,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
public ValueSetExpander.ValueSetExpansionOutcome expandVS(org.hl7.fhir.r5.model.ValueSet source, boolean cacheOk, boolean heiarchical) {
ValueSet convertedSource = null;
try {
- convertedSource = new VersionConvertor_10_50(myAdvisor).convertValueSet(source);
+ convertedSource = convertValueSet(source);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -596,7 +638,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
org.hl7.fhir.r5.model.ValueSet convertedResult = null;
if (expanded.getValueset() != null) {
try {
- convertedResult = new VersionConvertor_10_50(myAdvisor).convertValueSet(expanded.getValueset());
+ convertedResult = convertValueSet(expanded.getValueset());
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -618,7 +660,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
ValueSet.ConceptSetComponent convertedInc = null;
if (inc != null) {
try {
- convertedInc = new VersionConvertor_10_50(myAdvisor).convertConceptSetComponent(inc);
+ convertedInc = convertConceptSetComponent(inc);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -628,7 +670,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent valueSetExpansionComponent = null;
if (expansion != null) {
try {
- valueSetExpansionComponent = new VersionConvertor_10_50(myAdvisor).convertValueSetExpansionComponent(expansion);
+ valueSetExpansionComponent = convertValueSetExpansionComponent(expansion);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -733,6 +775,11 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
return fetchResource(org.hl7.fhir.r5.model.StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+typeName);
}
+ @Override
+ public org.hl7.fhir.r5.model.StructureDefinition fetchRawProfile(String url) {
+ return fetchResource(org.hl7.fhir.r5.model.StructureDefinition.class, url);
+ }
+
@Override
public void setUcumService(UcumService ucumService) {
throw new UnsupportedOperationException();
@@ -825,7 +872,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
try {
if (vs != null) {
- convertedVs = new VersionConvertor_10_50(myAdvisor).convertValueSet(vs);
+ convertedVs = convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -840,8 +887,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
ValueSet convertedVs = null;
try {
if (vs != null) {
- VersionConvertorAdvisor50 advisor50 = new NullVersionConverterAdvisor50();
- convertedVs = new VersionConvertor_10_50(advisor50).convertValueSet(vs);
+ convertedVs = convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -858,10 +904,10 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
try {
if (code != null) {
- convertedCode = new VersionConvertor_10_50(myAdvisor).convertCoding(code);
+ convertedCode = convertCoding(code);
}
if (vs != null) {
- convertedVs = new VersionConvertor_10_50(myAdvisor).convertValueSet(vs);
+ convertedVs = convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -878,10 +924,10 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
try {
if (code != null) {
- convertedCode = new VersionConvertor_10_50(myAdvisor).convertCodeableConcept(code);
+ convertedCode = VersionConvertor_10_50.convertCodeableConcept(code);
}
if (vs != null) {
- convertedVs = new VersionConvertor_10_50(myAdvisor).convertValueSet(vs);
+ convertedVs = convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/HapiWorkerContext.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/HapiWorkerContext.java
index 9cdae210cd8..1788fd582a5 100644
--- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/HapiWorkerContext.java
+++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/instance/hapi/validation/HapiWorkerContext.java
@@ -199,7 +199,7 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander
nextSystem = nextComposeConceptSet.getSystem();
}
- if (StringUtils.equals(nextSystem, nextComposeConceptSet.getSystem())) {
+ if (Constants.codeSystemNotNeeded(theSystem) || StringUtils.equals(nextSystem, nextComposeConceptSet.getSystem())) {
for (ConceptReferenceComponent nextComposeCode : nextComposeConceptSet.getConcept()) {
ConceptDefinitionComponent conceptDef = new ConceptDefinitionComponent();
conceptDef.setCode(nextComposeCode.getCode());
@@ -211,7 +211,13 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander
}
if (nextComposeConceptSet.getConcept().isEmpty()){
- ValidationResult result = validateCode(nextSystem, theCode, null);
+
+ String validateSystem = nextSystem;
+ if (Constants.codeSystemNotNeeded(nextSystem)) {
+ validateSystem = nextComposeConceptSet.getSystem();
+ }
+
+ ValidationResult result = validateCode(validateSystem, theCode, null);
if (result.isOk()){
return result;
}
diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/hapi/validation/FhirInstanceValidator.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/hapi/validation/FhirInstanceValidator.java
index d7c52d229a1..d5441294501 100644
--- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/hapi/validation/FhirInstanceValidator.java
+++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/hapi/validation/FhirInstanceValidator.java
@@ -59,7 +59,8 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
private IValidationSupport myValidationSupport;
private boolean noTerminologyChecks = false;
private volatile WorkerContextWrapper myWrappedWorkerContext;
-
+ private IResourceValidator.IValidatorResourceFetcher validatorResourceFetcher;
+ private boolean assumeValidRestReferences;
private boolean errorForUnknownProfiles;
private List extensionDomains = Collections.emptyList();
@@ -225,13 +226,32 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
.setErrorForUnknownProfiles(isErrorForUnknownProfiles())
.setExtensionDomains(getExtensionDomains())
.setNoTerminologyChecks(isNoTerminologyChecks())
+ .setValidatorResourceFetcher(getValidatorResourceFetcher())
+ .setAssumeValidRestReferences(isAssumeValidRestReferences())
.validate(wrappedWorkerContext, theValidationCtx);
}
+ public IResourceValidator.IValidatorResourceFetcher getValidatorResourceFetcher() {
+ return validatorResourceFetcher;
+ }
+
+ public void setValidatorResourceFetcher(IResourceValidator.IValidatorResourceFetcher validatorResourceFetcher) {
+ this.validatorResourceFetcher = validatorResourceFetcher;
+ }
+
+
private List getExtensionDomains() {
return extensionDomains;
}
+ public boolean isAssumeValidRestReferences() {
+ return assumeValidRestReferences;
+ }
+
+ public void setAssumeValidRestReferences(boolean assumeValidRestReferences) {
+ this.assumeValidRestReferences = assumeValidRestReferences;
+ }
+
private static class WorkerContextWrapper implements IWorkerContext {
private final HapiWorkerContext myWrap;
@@ -317,7 +337,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
retVal = new ArrayList<>();
for (StructureDefinition next : myWrap.allStructures()) {
try {
- retVal.add(org.hl7.fhir.convertors.conv40_50.StructureDefinition.convertStructureDefinition(next));
+ retVal.add(org.hl7.fhir.convertors.conv40_50.StructureDefinition40_50.convertStructureDefinition(next));
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -347,7 +367,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent conceptDefinition = null;
if (theResult.asConceptDefinition() != null) {
try {
- conceptDefinition = org.hl7.fhir.convertors.conv40_50.CodeSystem.convertConceptDefinitionComponent(theResult.asConceptDefinition());
+ conceptDefinition = org.hl7.fhir.convertors.conv40_50.CodeSystem40_50.convertConceptDefinitionComponent(theResult.asConceptDefinition());
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -367,7 +387,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
public ValueSetExpander.ValueSetExpansionOutcome expandVS(org.hl7.fhir.r5.model.ValueSet source, boolean cacheOk, boolean heiarchical) {
ValueSet convertedSource;
try {
- convertedSource = org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(source);
+ convertedSource = org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(source);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -376,7 +396,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
org.hl7.fhir.r5.model.ValueSet convertedResult = null;
if (expanded.getValueset() != null) {
try {
- convertedResult = org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(expanded.getValueset());
+ convertedResult = org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(expanded.getValueset());
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -398,7 +418,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
ValueSet.ConceptSetComponent convertedInc = null;
if (inc != null) {
try {
- convertedInc = org.hl7.fhir.convertors.conv40_50.ValueSet.convertConceptSetComponent(inc);
+ convertedInc = org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertConceptSetComponent(inc);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -408,7 +428,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
org.hl7.fhir.r5.model.ValueSet valueSetExpansion = null;
if (expansion != null) {
try {
- valueSetExpansion = org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(expansion.getValueset());
+ valueSetExpansion = org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(expansion.getValueset());
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -424,7 +444,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
return null;
}
try {
- return org.hl7.fhir.convertors.conv40_50.CodeSystem.convertCodeSystem(fetched);
+ return org.hl7.fhir.convertors.conv40_50.CodeSystem40_50.convertCodeSystem(fetched);
} catch (FHIRException e) {
throw new InternalErrorException(e);
}
@@ -509,6 +529,11 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
return fetchResource(org.hl7.fhir.r5.model.StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + typeName);
}
+ @Override
+ public org.hl7.fhir.r5.model.StructureDefinition fetchRawProfile(String url) {
+ return fetchResource(org.hl7.fhir.r5.model.StructureDefinition.class, url);
+ }
+
@Override
public List getTypeNames() {
return myWrap.getTypeNames();
@@ -605,7 +630,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
try {
if (vs != null) {
- convertedVs = org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(vs);
+ convertedVs = org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -620,7 +645,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
ValueSet convertedVs = null;
try {
if (vs != null) {
- convertedVs = org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(vs);
+ convertedVs = org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -640,7 +665,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
convertedCode = VersionConvertor_40_50.convertCoding(code);
}
if (vs != null) {
- convertedVs = org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(vs);
+ convertedVs = org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
@@ -660,7 +685,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r4.hapi.validation.BaseV
convertedCode = VersionConvertor_40_50.convertCodeableConcept(code);
}
if (vs != null) {
- convertedVs = org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(vs);
+ convertedVs = org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(vs);
}
} catch (FHIRException e) {
throw new InternalErrorException(e);
diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/r5/hapi/validation/FhirInstanceValidator.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/r5/hapi/validation/FhirInstanceValidator.java
index 02a3fd839d2..a6ced0b4654 100644
--- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/r5/hapi/validation/FhirInstanceValidator.java
+++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/r5/hapi/validation/FhirInstanceValidator.java
@@ -54,7 +54,9 @@ public class FhirInstanceValidator extends org.hl7.fhir.r5.hapi.validation.BaseV
private boolean noTerminologyChecks = false;
private volatile WorkerContextWrapper myWrappedWorkerContext;
private boolean errorForUnknownProfiles;
+ private boolean assumeValidRestReferences;
private List myExtensionDomains = Collections.emptyList();
+ private IResourceValidator.IValidatorResourceFetcher validatorResourceFetcher;
/**
* Constructor
@@ -220,9 +222,27 @@ public class FhirInstanceValidator extends org.hl7.fhir.r5.hapi.validation.BaseV
.setErrorForUnknownProfiles(isErrorForUnknownProfiles())
.setExtensionDomains(getExtensionDomains())
.setNoTerminologyChecks(isNoTerminologyChecks())
+ .setValidatorResourceFetcher(getValidatorResourceFetcher())
+ .setAssumeValidRestReferences(isAssumeValidRestReferences())
.validate(wrappedWorkerContext, theValidationCtx);
}
+ public IResourceValidator.IValidatorResourceFetcher getValidatorResourceFetcher() {
+ return validatorResourceFetcher;
+ }
+
+ public void setValidatorResourceFetcher(IResourceValidator.IValidatorResourceFetcher validatorResourceFetcher) {
+ this.validatorResourceFetcher = validatorResourceFetcher;
+ }
+
+ public boolean isAssumeValidRestReferences() {
+ return assumeValidRestReferences;
+ }
+
+ public void setAssumeValidRestReferences(boolean assumeValidRestReferences) {
+ this.assumeValidRestReferences = assumeValidRestReferences;
+ }
+
private static class WorkerContextWrapper implements IWorkerContext {
private final HapiWorkerContext myWrap;
@@ -514,6 +534,11 @@ public class FhirInstanceValidator extends org.hl7.fhir.r5.hapi.validation.BaseV
return fetchResource(org.hl7.fhir.r5.model.StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + typeName);
}
+ @Override
+ public StructureDefinition fetchRawProfile(String url) {
+ return myWrap.fetchRawProfile(url);
+ }
+
@Override
public List getTypeNames() {
return myWrap.getTypeNames();
@@ -706,7 +731,7 @@ public class FhirInstanceValidator extends org.hl7.fhir.r5.hapi.validation.BaseV
}
@Override
- public Base resolveReference(Object appContext, String url) throws FHIRException {
+ public Base resolveReference(Object appContext, String url, Base refContext) throws FHIRException {
return null;
}
diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java
index bace1c7268e..29fbca55962 100644
--- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java
+++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java
@@ -24,10 +24,12 @@ import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent;
import org.hl7.fhir.dstu3.utils.FHIRPathEngine;
import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.r5.utils.IResourceValidator;
import org.junit.*;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
+import org.mockito.internal.matchers.Any;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -41,8 +43,7 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
public class FhirInstanceValidatorDstu3Test {
@@ -975,7 +976,7 @@ public class FhirInstanceValidatorDstu3Test {
myInstanceVal.setValidationSupport(myMockSupport);
ValidationResult output = myVal.validateWithResult(input);
List errors = logResultsAndReturnNonInformationalOnes(output);
- assertThat(errors.toString(), containsString("StructureDefinition reference \"http://foo/structuredefinition/myprofile\" could not be resolved"));
+ assertThat(errors.toString(), containsString("Profile reference 'http://foo/structuredefinition/myprofile' could not be resolved, so has not been checked"));
}
@Test
@@ -1145,6 +1146,20 @@ public class FhirInstanceValidatorDstu3Test {
ourLog.info(output.getMessages().get(0).getMessage());
}
+ @Test
+ public void testInvocationOfValidatorFetcher() throws IOException {
+ String input = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/dstu3-rick-test.json"), Charsets.UTF_8);
+
+ IResourceValidator.IValidatorResourceFetcher resourceFetcher = mock(IResourceValidator.IValidatorResourceFetcher.class);
+ when(resourceFetcher.validationPolicy(any(),anyString(), anyString())).thenReturn(IResourceValidator.ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS);
+ myInstanceVal.setValidatorResourceFetcher(resourceFetcher);
+ myVal.validateWithResult(input);
+
+ verify(resourceFetcher, times(3)).resolveURL(any(), anyString(), anyString());
+ verify(resourceFetcher, times(4)).validationPolicy(any(), anyString(), anyString());
+ verify(resourceFetcher, times(4)).fetch(any(), anyString());
+ }
+
@Test
public void testValueWithWhitespace() throws IOException {
String input = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/dstu3-rick-test.json"), Charsets.UTF_8);
diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireResponseValidatorDstu3Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireResponseValidatorDstu3Test.java
index d4bbfac740e..7cbd9968f1e 100644
--- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireResponseValidatorDstu3Test.java
+++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireResponseValidatorDstu3Test.java
@@ -704,7 +704,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
coding.setCode("1293");
QuestionnaireResponseItemAnswerComponent answer = qrItem.addAnswer();
answer.setValue(coding);
- coding.addExtension("http://hl7.org/fhir/StructureDefinition/questionnaire-hidden", new BooleanType(true));
+ coding.addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-CO-value", new DecimalType("1.0"));
qr.addItem().setLinkId("2B").addAnswer().setValue(new BooleanType(true));
String reference = qr.getQuestionnaire().getReference();
diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireValidatorDstu3Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireValidatorDstu3Test.java
index 4a8ececb99a..9e8a25f5a42 100644
--- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireValidatorDstu3Test.java
+++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/QuestionnaireValidatorDstu3Test.java
@@ -20,6 +20,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
+import java.util.stream.Collectors;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
@@ -71,7 +72,7 @@ public class QuestionnaireValidatorDstu3Test {
ValidationResult errors = myVal.validateWithResult(q);
ourLog.info(errors.toString());
assertThat(errors.isSuccessful(), Matchers.is(true));
- assertThat(errors.getMessages(), Matchers.empty());
+ assertThat(errors.getMessages().stream().filter(t->t.getSeverity().ordinal() > ResultSeverityEnum.INFORMATION.ordinal()).collect(Collectors.toList()), Matchers.empty());
}
}
diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java
index ce094c1a8a8..d666335bed8 100644
--- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java
+++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java
@@ -66,8 +66,12 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class FhirInstanceValidatorR4Test extends BaseTest {
@@ -279,6 +283,33 @@ public class FhirInstanceValidatorR4Test extends BaseTest {
assertEquals("Primitive types must have a value that is not empty", all.get(0).getMessage());
}
+ /**
+ * See #1740
+ */
+ @Ignore
+ @Test
+ public void testValidateScalarInRepeatableField() {
+ String operationDefinition = "{\n" +
+ " \"resourceType\": \"OperationDefinition\",\n" +
+ " \"name\": \"Questionnaire\",\n" +
+ " \"status\": \"draft\",\n" +
+ " \"kind\" : \"operation\",\n" +
+ " \"code\": \"populate\",\n" +
+ " \"resource\": \"Patient\",\n" + // should be array
+ " \"system\": false,\n" + " " +
+ " \"type\": false,\n" +
+ " \"instance\": true\n" +
+ "}";
+
+ FhirValidator val = ourCtx.newValidator();
+ val.registerValidatorModule(new FhirInstanceValidator(myDefaultValidationSupport));
+
+ ValidationResult result = val.validateWithResult(operationDefinition);
+ List all = logResultsAndReturnAll(result);
+ assertFalse(result.isSuccessful());
+ assertEquals("Primitive types must have a value that is not empty", all.get(0).getMessage());
+ }
+
/**
* See #1676 - We should ignore schema location
*/
@@ -397,7 +428,11 @@ public class FhirInstanceValidatorR4Test extends BaseTest {
ValidationResult output = myVal.validateWithResult(encoded);
List errors = logResultsAndReturnNonInformationalOnes(output);
- assertEquals(46, errors.size());
+ errors = errors
+ .stream()
+ .filter(t -> t.getMessage().contains("Bundle entry missing fullUrl"))
+ .collect(Collectors.toList());
+ assertEquals(5, errors.size());
}
@Test
@@ -633,8 +668,8 @@ public class FhirInstanceValidatorR4Test extends BaseTest {
CachingValidationSupport support = new CachingValidationSupport(new ValidationSupportChain(defaultSupport, valSupport));
// Prepopulate SDs
- valSupport.addStructureDefinition(loadStructureDefinition(defaultSupport, "/dstu3/myconsent-profile.xml"));
- valSupport.addStructureDefinition(loadStructureDefinition(defaultSupport, "/dstu3/myconsent-ext.xml"));
+ valSupport.addStructureDefinition(loadStructureDefinition(defaultSupport, "/r4/myconsent-profile.xml"));
+ valSupport.addStructureDefinition(loadStructureDefinition(defaultSupport, "/r4/myconsent-ext.xml"));
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new FhirInstanceValidator(support));
@@ -652,6 +687,7 @@ public class FhirInstanceValidatorR4Test extends BaseTest {
.setSystem("http://terminology.hl7.org/CodeSystem/consentcategorycodes")
.setCode("acd");
+
// Should pass
ValidationResult output = val.validateWithResult(input);
List all = logResultsAndReturnErrorOnes(output);
@@ -1031,7 +1067,10 @@ public class FhirInstanceValidatorR4Test extends BaseTest {
myInstanceVal.setValidationSupport(myMockSupport);
ValidationResult output = myVal.validateWithResult(input);
List errors = logResultsAndReturnNonInformationalOnes(output);
- assertThat(errors.toString(), containsString("StructureDefinition reference \"http://foo/structuredefinition/myprofile\" could not be resolved"));
+
+ assertEquals(1, errors.size());
+ assertEquals("Profile reference 'http://foo/structuredefinition/myprofile' could not be resolved, so has not been checked", errors.get(0).getMessage());
+ assertEquals(ResultSeverityEnum.ERROR, errors.get(0).getSeverity());
}
@Test
@@ -1087,7 +1126,7 @@ public class FhirInstanceValidatorR4Test extends BaseTest {
@Ignore
public void testValidateDecimalWithTrailingDot() {
String input = "{" +
- " \"resourceType\": \"Observation\"," +
+ " \"resourceType\": \"Observation\"," +
" \"status\": \"final\"," +
" \"subject\": {\"reference\":\"Patient/123\"}," +
" \"code\": { \"coding\": [{ \"system\":\"http://foo\", \"code\":\"123\" }] }," +
@@ -1103,8 +1142,8 @@ public class FhirInstanceValidatorR4Test extends BaseTest {
" },\n" +
" \"text\": \"210.0-925.\"\n" +
" }\n" +
- " ]"+
- "}";
+ " ]" +
+ "}";
ourLog.info(input);
ValidationResult output = myVal.validateWithResult(input);
logResultsAndReturnAll(output);
@@ -1250,6 +1289,21 @@ public class FhirInstanceValidatorR4Test extends BaseTest {
assertEquals(0, all.size());
}
+ @Test
+ public void testInvocationOfValidatorFetcher() throws IOException {
+
+ String encoded = loadResource("/r4/r4-caredove-bundle.json");
+
+ IResourceValidator.IValidatorResourceFetcher resourceFetcher = mock(IResourceValidator.IValidatorResourceFetcher.class);
+ when(resourceFetcher.validationPolicy(any(), anyString(), anyString())).thenReturn(IResourceValidator.ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS);
+ myInstanceVal.setValidatorResourceFetcher(resourceFetcher);
+ myVal.validateWithResult(encoded);
+
+ verify(resourceFetcher, times(14)).resolveURL(any(), anyString(), anyString());
+ verify(resourceFetcher, times(12)).validationPolicy(any(), anyString(), anyString());
+ verify(resourceFetcher, times(12)).fetch(any(), anyString());
+ }
+
@Test
@Ignore
public void testValidateStructureDefinition() throws IOException {
diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/QuestionnaireValidatorR4Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/QuestionnaireValidatorR4Test.java
index b6b88d44c15..ff872af31f4 100644
--- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/QuestionnaireValidatorR4Test.java
+++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/QuestionnaireValidatorR4Test.java
@@ -23,6 +23,8 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.stream.Collectors;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
@@ -72,7 +74,7 @@ public class QuestionnaireValidatorR4Test {
ValidationResult errors = myVal.validateWithResult(q);
ourLog.info(errors.toString());
assertThat(errors.isSuccessful(), Matchers.is(true));
- assertThat(errors.getMessages(), Matchers.empty());
+ assertThat(errors.getMessages().stream().filter(t->t.getSeverity().ordinal() > ResultSeverityEnum.INFORMATION.ordinal()).collect(Collectors.toList()), Matchers.empty());
}
}
diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r5/validation/FhirInstanceValidatorR5Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r5/validation/FhirInstanceValidatorR5Test.java
index 3a4380a3a20..05a8e54e3ff 100644
--- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r5/validation/FhirInstanceValidatorR5Test.java
+++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r5/validation/FhirInstanceValidatorR5Test.java
@@ -53,9 +53,10 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.times;
public class FhirInstanceValidatorR5Test {
@@ -415,6 +416,23 @@ public class FhirInstanceValidatorR5Test {
assertThat(nonInfo, empty());
}
+
+
+ @Test
+ public void testInvocationOfValidatorFetcher() throws IOException {
+
+ String input = IOUtils.toString(FhirInstanceValidator.class.getResourceAsStream("/vitals.json"), Charsets.UTF_8);
+
+ IResourceValidator.IValidatorResourceFetcher resourceFetcher = mock(IResourceValidator.IValidatorResourceFetcher.class);
+ when(resourceFetcher.validationPolicy(any(),anyString(), anyString())).thenReturn(IResourceValidator.ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS);
+ myInstanceVal.setValidatorResourceFetcher(resourceFetcher);
+ myVal.validateWithResult(input);
+
+ verify(resourceFetcher, times(12)).resolveURL(any(), anyString(), anyString());
+ verify(resourceFetcher, times(3)).validationPolicy(any(), anyString(), anyString());
+ verify(resourceFetcher, times(3)).fetch(any(), anyString());
+ }
+
@Test
public void testIsNoTerminologyChecks() {
assertFalse(myInstanceVal.isNoTerminologyChecks());
@@ -774,7 +792,7 @@ public class FhirInstanceValidatorR5Test {
myInstanceVal.setValidationSupport(myMockSupport);
ValidationResult output = myVal.validateWithResult(input);
List errors = logResultsAndReturnNonInformationalOnes(output);
- assertThat(errors.toString(), containsString("StructureDefinition reference \"http://foo/structuredefinition/myprofile\" could not be resolved"));
+ assertThat(errors.toString(), containsString("Profile reference 'http://foo/structuredefinition/myprofile' could not be resolved, so has not been checked"));
}
@Test
diff --git a/hapi-fhir-validation/src/test/resources/r4/myconsent-ext.xml b/hapi-fhir-validation/src/test/resources/r4/myconsent-ext.xml
new file mode 100644
index 00000000000..2049e440b22
--- /dev/null
+++ b/hapi-fhir-validation/src/test/resources/r4/myconsent-ext.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-validation/src/test/resources/r4/myconsent-profile.xml b/hapi-fhir-validation/src/test/resources/r4/myconsent-profile.xml
new file mode 100644
index 00000000000..0396797fe88
--- /dev/null
+++ b/hapi-fhir-validation/src/test/resources/r4/myconsent-profile.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-validation/src/test/resources/vitals.json b/hapi-fhir-validation/src/test/resources/vitals.json
new file mode 100644
index 00000000000..78b3e733c6b
--- /dev/null
+++ b/hapi-fhir-validation/src/test/resources/vitals.json
@@ -0,0 +1,97 @@
+{
+ "resourceType": "Observation",
+ "id": "satO2",
+ "meta": {
+ "profile": [
+ "http://hl7.org/fhir/StructureDefinition/vitalsigns"
+ ]
+ },
+ "text": {
+ "status": "generated",
+ "div": "Generated Narrative with Details
id: satO2
meta:
identifier: o1223435-10
partOf: Procedure/ob
status: final
category: Vital Signs (Details : {http://terminology.hl7.org/CodeSystem/observation-category code 'vital-signs' = 'Vital Signs', given as 'Vital Signs'})
code: Oxygen saturation in Arterial blood (Details : {LOINC code '2708-6' = 'Oxygen saturation in Arterial blood', given as 'Oxygen saturation in Arterial blood'}; {LOINC code '59408-5' = 'Oxygen saturation in Arterial blood by Pulse oximetry', given as 'Oxygen saturation in Arterial blood by Pulse oximetry'}; {urn:iso:std:iso:11073:10101 code '150456' = '150456', given as 'MDC_PULS_OXIM_SAT_O2'})
subject: Patient/example
effective: Dec 5, 2014 9:30:10 AM
value: 95 % (Details: UCUM code % = '%')
interpretation: Normal (applies to non-numeric results) (Details : {http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation code 'N' = 'Normal', given as 'Normal'})
device: DeviceMetric/example
ReferenceRanges
- Low High * 90 % (Details: UCUM code % = '%') 99 % (Details: UCUM code % = '%')
"
+ },
+ "identifier": [
+ {
+ "system": "http://goodcare.org/observation/id",
+ "value": "o1223435-10"
+ }
+ ],
+ "partOf": [
+ {
+ "reference": "Procedure/ob"
+ }
+ ],
+ "status": "final",
+ "category": [
+ {
+ "coding": [
+ {
+ "system": "http://terminology.hl7.org/CodeSystem/observation-category",
+ "code": "vital-signs",
+ "display": "Vital Signs"
+ }
+ ],
+ "text": "Vital Signs"
+ }
+ ],
+ "code": {
+ "coding": [
+ {
+ "system": "http://loinc.org",
+ "code": "2708-6",
+ "display": "Oxygen saturation in Arterial blood"
+ },
+ {
+ "system": "http://loinc.org",
+ "code": "59408-5",
+ "display": "Oxygen saturation in Arterial blood by Pulse oximetry"
+ },
+ {
+ "system": "urn:iso:std:iso:11073:10101",
+ "code": "150456",
+ "display": "MDC_PULS_OXIM_SAT_O2"
+ }
+ ]
+ },
+ "subject": {
+ "reference": "Patient/example"
+ },
+ "effectiveDateTime": "2014-12-05T09:30:10+01:00",
+ "valueQuantity": {
+ "value": 95,
+ "unit": "%",
+ "system": "http://unitsofmeasure.org",
+ "code": "%"
+ },
+ "interpretation": [
+ {
+ "coding": [
+ {
+ "system": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation",
+ "code": "N",
+ "display": "Normal"
+ }
+ ],
+ "text": "Normal (applies to non-numeric results)"
+ }
+ ],
+ "device": {
+ "reference": "DeviceMetric/example"
+ },
+ "referenceRange": [
+ {
+ "low": {
+ "value": 90,
+ "unit": "%",
+ "system": "http://unitsofmeasure.org",
+ "code": "%"
+ },
+ "high": {
+ "value": 99,
+ "unit": "%",
+ "system": "http://unitsofmeasure.org",
+ "code": "%"
+ }
+ }
+ ]
+}
diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml
index ec1362ebd4c..4caaad9f81f 100644
--- a/hapi-tinder-plugin/pom.xml
+++ b/hapi-tinder-plugin/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../pom.xml
@@ -58,37 +58,37 @@
ca.uhn.hapi.fhir
hapi-fhir-structures-dstu3
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-structures-hl7org-dstu2
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-structures-r4
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-structures-r5
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-validation-resources-dstu2
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-validation-resources-dstu3
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-validation-resources-r4
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
org.apache.velocity
diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml
index 9e07aca1de0..55d2ca62a4f 100644
--- a/hapi-tinder-test/pom.xml
+++ b/hapi-tinder-test/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../pom.xml
diff --git a/pom.xml b/pom.xml
index a087edddc55..92dbf5e6403 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-fhir
pom
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
HAPI-FHIR
An open-source implementation of the FHIR specification in Java.
https://hapifhir.io
@@ -606,7 +606,7 @@
- 4.1.42-SNAPSHOT
+ 4.2.1-SNAPSHOT
1.0.2
-Dfile.encoding=UTF-8 -Xmx2048m
@@ -679,6 +679,7 @@
UTF-8
1.0.1
+ 1.13.0
5.4.1
@@ -1036,6 +1037,11 @@
httpcore
${httpcore_version}
+
+ co.elastic.apm
+ apm-agent-api
+ ${elastic_apm_version}
+
org.apache.jena
apache-jena-libs
diff --git a/restful-server-example/pom.xml b/restful-server-example/pom.xml
index 69440e2adf4..4813953ee4a 100644
--- a/restful-server-example/pom.xml
+++ b/restful-server-example/pom.xml
@@ -8,7 +8,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../pom.xml
diff --git a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml
index acc1aa4da1b..5c69d2bfd64 100644
--- a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml
+++ b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../../pom.xml
diff --git a/tests/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml
index e2c2c0c28dc..f3a5689802a 100644
--- a/tests/hapi-fhir-base-test-mindeps-client/pom.xml
+++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../../pom.xml
diff --git a/tests/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml
index 2b0fddd66ed..56809aad658 100644
--- a/tests/hapi-fhir-base-test-mindeps-server/pom.xml
+++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 4.2.0-SNAPSHOT
+ 4.3.0-SNAPSHOT
../../pom.xml