Add UserSelected and Version to resource tag (#4591)
* First commit: Add userSelected and version to ResourceTag and ResourceHistoryTag. Add migration step to migration tasks. For some reason SchemaMigrationTest is failing. * Fix nullability, update constructors, truncate versions over 30 chars. * yay we're done just cleanup * Checkpoint for recent changes. * Last commit before pausing work. * Fix bad code to find the version, tweak unit test pid ID to versionless and add TODO about why is update part of the test not passing? * Fix bad code in extractTagsRi(): Make it leverage the IBaseCoding variable already in the for loop. Fix bad code in populateResourceMetadataRi(). Leverage the existing BaseTag and use it to populate the IBaseCoding tag instance instead. Add more and better assertions in the unit test. * Merge rel_6_4 in * Current state for pairing * Fix CodingDt.getUserSelected method return code in tinder * Complete migration task and cleanup * Remove missed fixme * Bump version temporarily to use it for building core lib * Use primitive for compatibility with tinder generated CodingDt * Copyright updates * Hack to bypass NPE generated by bogus tinder-generated code * Simplify by removing temporary deprecations as version bump is needed anyway because of TagDefinition entity changes * Adjust tests * Fix migration task * Add test to show problem with tinder generated BooleanDt * More test adjustments * Improve BooleanDt NPE avoidance * Update core dep * Reverse Juan CVE VersionEnumTest changes. * Fix unit test. --------- Co-authored-by: Ken Stevens <ken@smilecdr.com> Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com> Co-authored-by: Tadgh <garygrantgraham@gmail.com>
This commit is contained in:
parent
ce46f4dd6a
commit
9d70dbd08f
|
@ -19,15 +19,14 @@ package ca.uhn.fhir.model.api;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* A single tag
|
||||
* <p>
|
||||
|
@ -115,12 +114,14 @@ public class Tag extends BaseElement implements IElement, IBaseCoding {
|
|||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
|
||||
Tag other = (Tag) obj;
|
||||
if (myScheme == null) {
|
||||
if (other.myScheme != null)
|
||||
return false;
|
||||
} else if (!myScheme.equals(other.myScheme))
|
||||
return false;
|
||||
|
||||
if (myTerm == null) {
|
||||
if (other.myTerm != null)
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 4204
|
||||
jira: SMILE-4688
|
||||
title: "With default configuration, Resource meta.tag properties: `userSelected` and `version`, were not stored in the database.
|
||||
This is now fixed."
|
|
@ -126,6 +126,7 @@ 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 javax.xml.stream.events.Characters;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
|
@ -143,7 +144,9 @@ import java.util.Set;
|
|||
import java.util.StringTokenizer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
import static org.apache.commons.lang3.BooleanUtils.isFalse;
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
@ -276,7 +279,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
TagList tagList = ResourceMetadataKeyEnum.TAG_LIST.get(theResource);
|
||||
if (tagList != null) {
|
||||
for (Tag next : tagList) {
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.TAG, next.getScheme(), next.getTerm(), next.getLabel());
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.TAG, next.getScheme(), next.getTerm(),
|
||||
next.getLabel(), next.getVersion(), next.getUserSelected());
|
||||
if (def != null) {
|
||||
ResourceTag tag = theEntity.addTag(def);
|
||||
allDefs.add(tag);
|
||||
|
@ -288,7 +292,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
List<BaseCodingDt> securityLabels = ResourceMetadataKeyEnum.SECURITY_LABELS.get(theResource);
|
||||
if (securityLabels != null) {
|
||||
for (BaseCodingDt next : securityLabels) {
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.SECURITY_LABEL, next.getSystemElement().getValue(), next.getCodeElement().getValue(), next.getDisplayElement().getValue());
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.SECURITY_LABEL, next.getSystemElement().getValue(),
|
||||
next.getCodeElement().getValue(), next.getDisplayElement().getValue(), null, null);
|
||||
if (def != null) {
|
||||
ResourceTag tag = theEntity.addTag(def);
|
||||
allDefs.add(tag);
|
||||
|
@ -300,7 +305,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
List<IdDt> profiles = ResourceMetadataKeyEnum.PROFILES.get(theResource);
|
||||
if (profiles != null) {
|
||||
for (IIdType next : profiles) {
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.PROFILE, NS_JPA_PROFILE, next.getValue(), null);
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.PROFILE, NS_JPA_PROFILE, next.getValue(), null, null, null);
|
||||
if (def != null) {
|
||||
ResourceTag tag = theEntity.addTag(def);
|
||||
allDefs.add(tag);
|
||||
|
@ -314,7 +319,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
List<? extends IBaseCoding> tagList = theResource.getMeta().getTag();
|
||||
if (tagList != null) {
|
||||
for (IBaseCoding next : tagList) {
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.TAG, next.getSystem(), next.getCode(), next.getDisplay());
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.TAG, next.getSystem(), next.getCode(),
|
||||
next.getDisplay(), next.getVersion(), next.getUserSelected());
|
||||
if (def != null) {
|
||||
ResourceTag tag = theEntity.addTag(def);
|
||||
theAllTags.add(tag);
|
||||
|
@ -326,7 +332,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
List<? extends IBaseCoding> securityLabels = theResource.getMeta().getSecurity();
|
||||
if (securityLabels != null) {
|
||||
for (IBaseCoding next : securityLabels) {
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.SECURITY_LABEL, next.getSystem(), next.getCode(), next.getDisplay());
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.SECURITY_LABEL, next.getSystem(), next.getCode(), next.getDisplay(), null, null);
|
||||
if (def != null) {
|
||||
ResourceTag tag = theEntity.addTag(def);
|
||||
theAllTags.add(tag);
|
||||
|
@ -338,7 +344,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
List<? extends IPrimitiveType<String>> profiles = theResource.getMeta().getProfile();
|
||||
if (profiles != null) {
|
||||
for (IPrimitiveType<String> next : profiles) {
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.PROFILE, NS_JPA_PROFILE, next.getValue(), null);
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, TagTypeEnum.PROFILE, NS_JPA_PROFILE, next.getValue(), null, null, null);
|
||||
if (def != null) {
|
||||
ResourceTag tag = theEntity.addTag(def);
|
||||
theAllTags.add(tag);
|
||||
|
@ -376,22 +382,25 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
/**
|
||||
* <code>null</code> will only be returned if the scheme and tag are both blank
|
||||
*/
|
||||
protected TagDefinition getTagOrNull(TransactionDetails theTransactionDetails, TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel) {
|
||||
protected TagDefinition getTagOrNull(TransactionDetails theTransactionDetails, TagTypeEnum theTagType, String theScheme,
|
||||
String theTerm, String theLabel, String theVersion, Boolean theUserSelected) {
|
||||
if (isBlank(theScheme) && isBlank(theTerm) && isBlank(theLabel)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MemoryCacheService.TagDefinitionCacheKey key = toTagDefinitionMemoryCacheKey(theTagType, theScheme, theTerm);
|
||||
MemoryCacheService.TagDefinitionCacheKey key = toTagDefinitionMemoryCacheKey(theTagType, theScheme, theTerm, theVersion, theUserSelected);
|
||||
|
||||
TagDefinition retVal = myMemoryCacheService.getIfPresent(MemoryCacheService.CacheEnum.TAG_DEFINITION, key);
|
||||
|
||||
if (retVal == null) {
|
||||
HashMap<MemoryCacheService.TagDefinitionCacheKey, TagDefinition> resolvedTagDefinitions = theTransactionDetails.getOrCreateUserData(HapiTransactionService.XACT_USERDATA_KEY_RESOLVED_TAG_DEFINITIONS, () -> new HashMap<>());
|
||||
HashMap<MemoryCacheService.TagDefinitionCacheKey, TagDefinition> resolvedTagDefinitions = theTransactionDetails
|
||||
.getOrCreateUserData(HapiTransactionService.XACT_USERDATA_KEY_RESOLVED_TAG_DEFINITIONS, HashMap::new);
|
||||
|
||||
retVal = resolvedTagDefinitions.get(key);
|
||||
|
||||
if (retVal == null) {
|
||||
// actual DB hit(s) happen here
|
||||
retVal = getOrCreateTag(theTagType, theScheme, theTerm, theLabel);
|
||||
retVal = getOrCreateTag(theTagType, theScheme, theTerm, theLabel, theVersion, theUserSelected);
|
||||
|
||||
TransactionSynchronization sync = new AddTagDefinitionToCacheAfterCommitSynchronization(key, retVal);
|
||||
TransactionSynchronizationManager.registerSynchronization(sync);
|
||||
|
@ -409,26 +418,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
* <p>
|
||||
* Can also throw an InternalErrorException if something bad happens.
|
||||
*/
|
||||
private TagDefinition getOrCreateTag(TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel) {
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<TagDefinition> cq = builder.createQuery(TagDefinition.class);
|
||||
Root<TagDefinition> from = cq.from(TagDefinition.class);
|
||||
private TagDefinition getOrCreateTag(TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel,
|
||||
String theVersion, Boolean theUserSelected) {
|
||||
|
||||
if (isNotBlank(theScheme)) {
|
||||
cq.where(
|
||||
builder.and(
|
||||
builder.equal(from.get("myTagType"), theTagType),
|
||||
builder.equal(from.get("mySystem"), theScheme),
|
||||
builder.equal(from.get("myCode"), theTerm)));
|
||||
} else {
|
||||
cq.where(
|
||||
builder.and(
|
||||
builder.equal(from.get("myTagType"), theTagType),
|
||||
builder.isNull(from.get("mySystem")),
|
||||
builder.equal(from.get("myCode"), theTerm)));
|
||||
}
|
||||
|
||||
TypedQuery<TagDefinition> q = myEntityManager.createQuery(cq);
|
||||
TypedQuery<TagDefinition> q = buildTagQuery(theTagType, theScheme, theTerm, theVersion, theUserSelected);
|
||||
|
||||
TransactionTemplate template = new TransactionTemplate(myTransactionManager);
|
||||
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
|
@ -450,6 +443,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
val = q.getSingleResult();
|
||||
} catch (NoResultException e) {
|
||||
val = new TagDefinition(theTagType, theScheme, theTerm, theLabel);
|
||||
val.setVersion(theVersion);
|
||||
val.setUserSelected(theUserSelected);
|
||||
myEntityManager.persist(val);
|
||||
}
|
||||
return val;
|
||||
|
@ -507,6 +502,34 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private TypedQuery<TagDefinition> buildTagQuery(TagTypeEnum theTagType, String theScheme, String theTerm,
|
||||
String theVersion, Boolean theUserSelected) {
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<TagDefinition> cq = builder.createQuery(TagDefinition.class);
|
||||
Root<TagDefinition> from = cq.from(TagDefinition.class);
|
||||
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
predicates.add(
|
||||
builder.and(
|
||||
builder.equal(from.get("myTagType"), theTagType),
|
||||
builder.equal(from.get("myCode"), theTerm)));
|
||||
|
||||
predicates.add( isBlank(theScheme)
|
||||
? builder.isNull(from.get("mySystem"))
|
||||
: builder.equal(from.get("mySystem"), theScheme));
|
||||
|
||||
predicates.add( isBlank(theVersion)
|
||||
? builder.isNull(from.get("myVersion"))
|
||||
: builder.equal(from.get("myVersion"), theVersion));
|
||||
|
||||
predicates.add( isNull(theUserSelected) || isFalse(theUserSelected)
|
||||
? builder.isFalse(from.get("myUserSelected"))
|
||||
: builder.isTrue(from.get("myUserSelected")));
|
||||
|
||||
cq.where(predicates.toArray(new Predicate[0]));
|
||||
return myEntityManager.createQuery(cq);
|
||||
}
|
||||
|
||||
|
||||
void incrementId(T theResource, ResourceTable theSavedEntity, IIdType theResourceId) {
|
||||
String newVersion;
|
||||
|
@ -741,10 +764,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
}
|
||||
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||
if (def.isStandardType() == false) {
|
||||
if ( ! def.isStandardType()) {
|
||||
String profile = def.getResourceProfile("");
|
||||
if (isNotBlank(profile)) {
|
||||
TagDefinition profileDef = getTagOrNull(theTransactionDetails, TagTypeEnum.PROFILE, NS_JPA_PROFILE, profile, null);
|
||||
TagDefinition profileDef = getTagOrNull(theTransactionDetails, TagTypeEnum.PROFILE, NS_JPA_PROFILE, profile, null, null, null);
|
||||
|
||||
ResourceTag tag = theEntity.addTag(profileDef);
|
||||
allDefs.add(tag);
|
||||
|
@ -1584,8 +1607,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
}
|
||||
|
||||
@Nonnull
|
||||
public static MemoryCacheService.TagDefinitionCacheKey toTagDefinitionMemoryCacheKey(TagTypeEnum theTagType, String theScheme, String theTerm) {
|
||||
return new MemoryCacheService.TagDefinitionCacheKey(theTagType, theScheme, theTerm);
|
||||
public static MemoryCacheService.TagDefinitionCacheKey toTagDefinitionMemoryCacheKey(
|
||||
TagTypeEnum theTagType, String theScheme, String theTerm, String theVersion, Boolean theUserSelected) {
|
||||
return new MemoryCacheService.TagDefinitionCacheKey(theTagType, theScheme, theTerm, theVersion, theUserSelected);
|
||||
}
|
||||
|
||||
static String cleanProvenanceSourceUri(String theProvenanceSourceUri) {
|
||||
|
|
|
@ -143,6 +143,7 @@ import java.util.Date;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
@ -740,9 +741,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
|
||||
boolean hasTag = false;
|
||||
for (BaseTag next : new ArrayList<>(theEntity.getTags())) {
|
||||
if (ObjectUtil.equals(next.getTag().getTagType(), nextDef.getTagType()) &&
|
||||
ObjectUtil.equals(next.getTag().getSystem(), nextDef.getSystem()) &&
|
||||
ObjectUtil.equals(next.getTag().getCode(), nextDef.getCode())) {
|
||||
if (Objects.equals(next.getTag().getTagType(), nextDef.getTagType()) &&
|
||||
Objects.equals(next.getTag().getSystem(), nextDef.getSystem()) &&
|
||||
Objects.equals(next.getTag().getCode(), nextDef.getCode()) &&
|
||||
Objects.equals(next.getTag().getVersion(), nextDef.getVersion()) &&
|
||||
Objects.equals(next.getTag().getUserSelected(), nextDef.getUserSelected())) {
|
||||
hasTag = true;
|
||||
break;
|
||||
}
|
||||
|
@ -751,7 +754,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
if (!hasTag) {
|
||||
theEntity.setHasTags(true);
|
||||
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, nextDef.getTagType(), nextDef.getSystem(), nextDef.getCode(), nextDef.getDisplay());
|
||||
TagDefinition def = getTagOrNull(theTransactionDetails, nextDef.getTagType(), nextDef.getSystem(),
|
||||
nextDef.getCode(), nextDef.getDisplay(), nextDef.getVersion(), nextDef.getUserSelected());
|
||||
if (def != null) {
|
||||
BaseTag newEntity = theEntity.addTag(def);
|
||||
if (newEntity.getTagId() == null) {
|
||||
|
|
|
@ -431,6 +431,8 @@ public class JpaStorageResourceParser implements IJpaStorageResourceParser {
|
|||
tag.setSystem(next.getTag().getSystem());
|
||||
tag.setCode(next.getTag().getCode());
|
||||
tag.setDisplay(next.getTag().getDisplay());
|
||||
tag.setVersion(next.getTag().getVersion());
|
||||
tag.setUserSelected(next.getTag().getUserSelected());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,9 +91,38 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
}
|
||||
|
||||
protected void init640() {
|
||||
Builder version = forVersion(VersionEnum.V6_4_0);
|
||||
|
||||
{
|
||||
Builder.BuilderWithTableName tagDefTable = version.onTable("HFJ_TAG_DEF");
|
||||
|
||||
// add columns
|
||||
tagDefTable
|
||||
.addColumn("20230209.1", "TAG_VERSION")
|
||||
.nullable()
|
||||
.type(ColumnTypeEnum.STRING, 30);
|
||||
tagDefTable
|
||||
.addColumn("20230209.2", "TAG_USER_SELECTED")
|
||||
.nullable()
|
||||
.type(ColumnTypeEnum.BOOLEAN);
|
||||
|
||||
// Update indexing
|
||||
tagDefTable.dropIndex("20230209.3", "IDX_TAGDEF_TYPESYSCODE");
|
||||
|
||||
tagDefTable.dropIndex("20230209.4", "IDX_TAGDEF_TYPESYSCODEVERUS");
|
||||
Map<DriverTypeEnum, String> addTagDefConstraint = new HashMap<>();
|
||||
addTagDefConstraint.put(DriverTypeEnum.H2_EMBEDDED, "ALTER TABLE HFJ_TAG_DEF ADD CONSTRAINT IDX_TAGDEF_TYPESYSCODEVERUS UNIQUE (TAG_TYPE, TAG_CODE, TAG_SYSTEM, TAG_VERSION, TAG_USER_SELECTED)");
|
||||
addTagDefConstraint.put(DriverTypeEnum.MARIADB_10_1, "ALTER TABLE HFJ_TAG_DEF ADD CONSTRAINT IDX_TAGDEF_TYPESYSCODEVERUS UNIQUE (TAG_TYPE, TAG_CODE, TAG_SYSTEM, TAG_VERSION, TAG_USER_SELECTED)");
|
||||
addTagDefConstraint.put(DriverTypeEnum.MSSQL_2012, "ALTER TABLE HFJ_TAG_DEF ADD CONSTRAINT IDX_TAGDEF_TYPESYSCODEVERUS UNIQUE (TAG_TYPE, TAG_CODE, TAG_SYSTEM, TAG_VERSION, TAG_USER_SELECTED)");
|
||||
addTagDefConstraint.put(DriverTypeEnum.MYSQL_5_7, "ALTER TABLE HFJ_TAG_DEF ADD CONSTRAINT IDX_TAGDEF_TYPESYSCODEVERUS UNIQUE (TAG_TYPE, TAG_CODE, TAG_SYSTEM, TAG_VERSION, TAG_USER_SELECTED)");
|
||||
addTagDefConstraint.put(DriverTypeEnum.ORACLE_12C, "ALTER TABLE HFJ_TAG_DEF ADD CONSTRAINT IDX_TAGDEF_TYPESYSCODEVERUS UNIQUE (TAG_TYPE, TAG_CODE, TAG_SYSTEM, TAG_VERSION, TAG_USER_SELECTED)");
|
||||
addTagDefConstraint.put(DriverTypeEnum.POSTGRES_9_4, "ALTER TABLE HFJ_TAG_DEF ADD CONSTRAINT IDX_TAGDEF_TYPESYSCODEVERUS UNIQUE (TAG_TYPE, TAG_CODE, TAG_SYSTEM, TAG_VERSION, TAG_USER_SELECTED)");
|
||||
version.executeRawSql("20230209.5", addTagDefConstraint);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected void init630() {
|
||||
Builder version = forVersion(VersionEnum.V6_3_0);
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@ import ca.uhn.fhir.rest.api.Constants;
|
|||
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
import org.hibernate.annotations.GeneratorType;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.OptimisticLock;
|
||||
import org.hibernate.search.engine.backend.types.Projectable;
|
||||
import org.hibernate.search.engine.backend.types.Searchable;
|
||||
|
@ -64,7 +64,6 @@ import javax.persistence.OneToMany;
|
|||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.PrePersist;
|
||||
import javax.persistence.PreUpdate;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.Version;
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.model.entity;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
@ -49,7 +50,8 @@ import java.util.Collection;
|
|||
@Index(name = "IDX_TAG_DEF_TP_CD_SYS", columnList = "TAG_TYPE, TAG_CODE, TAG_SYSTEM, TAG_ID"),
|
||||
},
|
||||
uniqueConstraints = {
|
||||
@UniqueConstraint(name = "IDX_TAGDEF_TYPESYSCODE", columnNames = {"TAG_TYPE", "TAG_SYSTEM", "TAG_CODE"})
|
||||
@UniqueConstraint(name = "IDX_TAGDEF_TYPESYSCODEVERUS",
|
||||
columnNames = {"TAG_TYPE", "TAG_SYSTEM", "TAG_CODE", "TAG_VERSION", "TAG_USER_SELECTED"})
|
||||
}
|
||||
)
|
||||
public class TagDefinition implements Serializable {
|
||||
|
@ -57,22 +59,35 @@ public class TagDefinition implements Serializable {
|
|||
private static final long serialVersionUID = 1L;
|
||||
@Column(name = "TAG_CODE", length = 200)
|
||||
private String myCode;
|
||||
|
||||
@Column(name = "TAG_DISPLAY", length = 200)
|
||||
private String myDisplay;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_TAGDEF_ID")
|
||||
@SequenceGenerator(name = "SEQ_TAGDEF_ID", sequenceName = "SEQ_TAGDEF_ID")
|
||||
@Column(name = "TAG_ID")
|
||||
private Long myId;
|
||||
|
||||
@OneToMany(cascade = {}, fetch = FetchType.LAZY, mappedBy = "myTag")
|
||||
private Collection<ResourceTag> myResources;
|
||||
|
||||
@OneToMany(cascade = {}, fetch = FetchType.LAZY, mappedBy = "myTag")
|
||||
private Collection<ResourceHistoryTag> myResourceVersions;
|
||||
|
||||
@Column(name = "TAG_SYSTEM", length = 200)
|
||||
private String mySystem;
|
||||
|
||||
@Column(name = "TAG_TYPE", nullable = false)
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
private TagTypeEnum myTagType;
|
||||
|
||||
@Column(name = "TAG_VERSION", length = 30)
|
||||
private String myVersion;
|
||||
|
||||
@Column(name = "TAG_USER_SELECTED")
|
||||
private boolean myUserSelected;
|
||||
|
||||
@Transient
|
||||
private transient Integer myHashCode;
|
||||
|
||||
|
@ -133,6 +148,27 @@ public class TagDefinition implements Serializable {
|
|||
myHashCode = null;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return myVersion;
|
||||
}
|
||||
|
||||
public void setVersion(String theVersion) {
|
||||
setVersionAfterTrim(theVersion);
|
||||
}
|
||||
|
||||
private void setVersionAfterTrim(String theVersion) {
|
||||
if (theVersion != null) {
|
||||
myVersion = StringUtils.truncate(theVersion, 30);
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean getUserSelected() { return myUserSelected; }
|
||||
|
||||
public void setUserSelected(Boolean theUserSelected) {
|
||||
myUserSelected = theUserSelected != null && theUserSelected;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
|
@ -151,6 +187,8 @@ public class TagDefinition implements Serializable {
|
|||
b.append(myTagType, other.myTagType);
|
||||
b.append(mySystem, other.mySystem);
|
||||
b.append(myCode, other.myCode);
|
||||
b.append(myVersion, other.myVersion);
|
||||
b.append(myUserSelected, other.myUserSelected);
|
||||
}
|
||||
|
||||
return b.isEquals();
|
||||
|
@ -163,6 +201,8 @@ public class TagDefinition implements Serializable {
|
|||
b.append(myTagType);
|
||||
b.append(mySystem);
|
||||
b.append(myCode);
|
||||
b.append(myVersion);
|
||||
b.append(myUserSelected);
|
||||
myHashCode = b.toHashCode();
|
||||
}
|
||||
return myHashCode;
|
||||
|
@ -175,6 +215,8 @@ public class TagDefinition implements Serializable {
|
|||
retVal.append("system", mySystem);
|
||||
retVal.append("code", myCode);
|
||||
retVal.append("display", myDisplay);
|
||||
retVal.append("version", myVersion);
|
||||
retVal.append("userSelected", myUserSelected);
|
||||
return retVal.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,11 @@ public class TagDefinitionTest {
|
|||
def.setCode("my_code");
|
||||
def.setSystem("my_system");
|
||||
def.setDisplay("my_display");
|
||||
assertEquals("TagDefinition[id=<null>,system=my_system,code=my_code,display=my_display]", def.toString());
|
||||
def.setVersion("V 1.0");
|
||||
def.setUserSelected(true);
|
||||
assertEquals(
|
||||
"TagDefinition[id=<null>,system=my_system,code=my_code,display=my_display,version=V 1.0,userSelected=true]",
|
||||
def.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -39,7 +43,8 @@ public class TagDefinitionTest {
|
|||
def.setCode("my_code");
|
||||
def.setSystem("my_system");
|
||||
def.setDisplay("my_display");
|
||||
assertEquals (-2125810377,def.hashCode());
|
||||
assertEquals (-2125810377,def.hashCode());
|
||||
def.setVersion("V 1.0");
|
||||
def.setUserSelected(true);
|
||||
assertEquals (434166476,def.hashCode());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,8 +65,8 @@ public class ExpandResourcesStepJpaTest extends BaseJpaR4Test {
|
|||
.boxed()
|
||||
.map(t -> {
|
||||
Patient p = new Patient();
|
||||
p.getMeta().addTag().setSystem("http://static").setCode("tag");
|
||||
p.getMeta().addTag().setSystem("http://dynamic").setCode("tag" + t);
|
||||
p.getMeta().addTag().setSystem("http://static").setCode("tag").setUserSelected(true).setVersion("1");
|
||||
p.getMeta().addTag().setSystem("http://dynamic").setCode("tag" + t).setUserSelected(true).setVersion("1");
|
||||
return myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
}).toList();
|
||||
assertEquals(count, ids.size());
|
||||
|
@ -91,10 +91,10 @@ public class ExpandResourcesStepJpaTest extends BaseJpaR4Test {
|
|||
verify(mySink, times(1)).accept(myWorkChunkCaptor.capture());
|
||||
ExpandedResourcesList expandedResourceList = myWorkChunkCaptor.getValue();
|
||||
assertEquals(10, expandedResourceList.getStringifiedResources().size());
|
||||
assertThat(expandedResourceList.getStringifiedResources().get(0), containsString("{\"system\":\"http://static\",\"code\":\"tag\"}"));
|
||||
assertThat(expandedResourceList.getStringifiedResources().get(0), containsString("{\"system\":\"http://dynamic\",\"code\":\"tag0\"}"));
|
||||
assertThat(expandedResourceList.getStringifiedResources().get(1), containsString("{\"system\":\"http://static\",\"code\":\"tag\"}"));
|
||||
assertThat(expandedResourceList.getStringifiedResources().get(1), containsString("{\"system\":\"http://dynamic\",\"code\":\"tag1\"}"));
|
||||
assertThat(expandedResourceList.getStringifiedResources().get(0), containsString("{\"system\":\"http://static\",\"version\":\"1\",\"code\":\"tag\",\"userSelected\":true}"));
|
||||
assertThat(expandedResourceList.getStringifiedResources().get(0), containsString("{\"system\":\"http://static\",\"version\":\"1\",\"code\":\"tag\",\"userSelected\":true}"));
|
||||
assertThat(expandedResourceList.getStringifiedResources().get(1), containsString("{\"system\":\"http://static\",\"version\":\"1\",\"code\":\"tag\",\"userSelected\":true}"));
|
||||
assertThat(expandedResourceList.getStringifiedResources().get(1), containsString("{\"system\":\"http://static\",\"version\":\"1\",\"code\":\"tag\",\"userSelected\":true}"));
|
||||
|
||||
// Verify query counts
|
||||
assertEquals(theExpectedSelectQueries, myCaptureQueriesListener.countSelectQueries());
|
||||
|
|
|
@ -77,12 +77,14 @@ public class BaseHapiFhirDaoTest {
|
|||
TagTypeEnum theEnum,
|
||||
String theScheme,
|
||||
String theTerm,
|
||||
String theLabel) {
|
||||
String theLabel,
|
||||
String theVersion,
|
||||
Boolean theUserSelected ) {
|
||||
// we need to init synchronization due to what
|
||||
// the underlying class is doing
|
||||
try {
|
||||
TransactionSynchronizationManager.initSynchronization();
|
||||
return super.getTagOrNull(theDetails, theEnum, theScheme, theTerm, theLabel);
|
||||
return super.getTagOrNull(theDetails, theEnum, theScheme, theTerm, theLabel, theVersion, theUserSelected);
|
||||
} finally {
|
||||
TransactionSynchronizationManager.clearSynchronization();
|
||||
}
|
||||
|
@ -175,12 +177,13 @@ public class BaseHapiFhirDaoTest {
|
|||
String scheme = "http://localhost";
|
||||
String term = "code123";
|
||||
String label = "hollow world";
|
||||
String version = "v1.0";
|
||||
Boolean userSelected = true;
|
||||
String raceConditionError = "Entity exists; if this is logged, you have race condition issues!";
|
||||
|
||||
TagDefinition tagDefinition = new TagDefinition(tagType,
|
||||
scheme,
|
||||
term,
|
||||
label);
|
||||
TagDefinition tagDefinition = new TagDefinition(tagType, scheme, term, label);
|
||||
tagDefinition.setVersion(version);
|
||||
tagDefinition.setUserSelected(userSelected);
|
||||
|
||||
// mock objects
|
||||
CriteriaBuilder builder = getMockedCriteriaBuilder();
|
||||
|
@ -270,7 +273,7 @@ public class BaseHapiFhirDaoTest {
|
|||
Runnable task = () -> {
|
||||
latch.countDown();
|
||||
try {
|
||||
TagDefinition retTag = myTestDao.getTagOrNull(new TransactionDetails(), tagType, scheme, term, label);
|
||||
TagDefinition retTag = myTestDao.getTagOrNull(new TransactionDetails(), tagType, scheme, term, label, version, userSelected);
|
||||
outcomes.put(retTag.hashCode(), retTag);
|
||||
counter.incrementAndGet();
|
||||
} catch (Exception ex) {
|
||||
|
@ -330,6 +333,8 @@ public class BaseHapiFhirDaoTest {
|
|||
String scheme = "http://localhost";
|
||||
String term = "code123";
|
||||
String label = "hollow world";
|
||||
String version = "v1.0";
|
||||
Boolean userSelected = true;
|
||||
TransactionDetails transactionDetails = new TransactionDetails();
|
||||
String exMsg = "Hi there";
|
||||
String readError = "No read for you";
|
||||
|
@ -358,7 +363,7 @@ public class BaseHapiFhirDaoTest {
|
|||
|
||||
// test
|
||||
try {
|
||||
myTestDao.getTagOrNull(transactionDetails, tagType, scheme, term, label);
|
||||
myTestDao.getTagOrNull(transactionDetails, tagType, scheme, term, label, version, userSelected);
|
||||
fail();
|
||||
} catch (Exception ex) {
|
||||
// verify
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTag;
|
||||
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.system.HapiTestSystemProperties;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.InstantType;
|
||||
import org.hl7.fhir.r4.model.Meta;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
|
@ -14,12 +19,16 @@ import org.hl7.fhir.r4.model.StringType;
|
|||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
@ -29,7 +38,9 @@ import java.util.stream.Collectors;
|
|||
import static ca.uhn.fhir.rest.api.Constants.PARAM_TAG;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.junit.jupiter.api.Assertions.assertAll;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
@ -142,6 +153,163 @@ public class FhirResourceDaoR4MetaTest extends BaseJpaR4Test {
|
|||
assertEquals("bar", patient2.getMeta().getSecurityFirstRep().getCode());
|
||||
}
|
||||
|
||||
@Nested
|
||||
public class TestTagWithVersionAndUserSelected {
|
||||
|
||||
private static final String expectedSystem1 = "http://foo";
|
||||
private static final String expectedCode1 = "code1";
|
||||
private static final String expectedVersion1 = "testVersion1";
|
||||
private static final String expectedDisplay1 = "Test1";
|
||||
private static final boolean expectedUserSelected1 = true;
|
||||
|
||||
private static final String expectedSystem2 = "http://another.system";
|
||||
private static final String expectedCode2 = "code2";
|
||||
private static final String expectedVersion2 = "testVersion2";
|
||||
private static final String expectedDisplay2 = "Test2";
|
||||
private static final boolean expectedUserSelected2 = false;
|
||||
|
||||
private static final class TagQtyExpectations {
|
||||
public int theTagQty;
|
||||
public int theTagV1Qty;
|
||||
public int theTagV2Qty;
|
||||
|
||||
public TagQtyExpectations(int theTheTagV1Qty, int theTheTagV2Qty) {
|
||||
theTagQty = theTheTagV1Qty + theTheTagV2Qty;
|
||||
theTagV1Qty = theTheTagV1Qty;
|
||||
theTagV2Qty = theTheTagV2Qty;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<DaoConfig.TagStorageModeEnum, TagQtyExpectations> expectedTagCountMap = Map.of(
|
||||
DaoConfig.TagStorageModeEnum.INLINE, new TagQtyExpectations(0, 1),
|
||||
DaoConfig.TagStorageModeEnum.NON_VERSIONED, new TagQtyExpectations(1, 1),
|
||||
DaoConfig.TagStorageModeEnum.VERSIONED, new TagQtyExpectations(1, 1)
|
||||
);
|
||||
|
||||
private static final Map<DaoConfig.TagStorageModeEnum, TagQtyExpectations> expectedHistoryTagCountMap = Map.of(
|
||||
DaoConfig.TagStorageModeEnum.INLINE, new TagQtyExpectations(0, 0),
|
||||
DaoConfig.TagStorageModeEnum.NON_VERSIONED, new TagQtyExpectations(0, 0),
|
||||
DaoConfig.TagStorageModeEnum.VERSIONED, new TagQtyExpectations(2, 1)
|
||||
);
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(DaoConfig.TagStorageModeEnum.class)
|
||||
public void testAddTagWithVersionAndUserSelected(DaoConfig.TagStorageModeEnum theTagStorageModeEnum) {
|
||||
|
||||
myDaoConfig.setTagStorageMode(theTagStorageModeEnum);
|
||||
|
||||
final Patient savedPatient = new Patient();
|
||||
final Coding newTag = savedPatient.getMeta()
|
||||
.addTag()
|
||||
.setSystem(expectedSystem1)
|
||||
.setCode(expectedCode1)
|
||||
.setDisplay(expectedDisplay1);
|
||||
assertFalse(newTag.getUserSelected());
|
||||
newTag.setVersion(expectedVersion1)
|
||||
.setUserSelected(expectedUserSelected1);
|
||||
savedPatient.setActive(true);
|
||||
final IIdType pid1 = myPatientDao.create(savedPatient, new SystemRequestDetails()).getId().toVersionless();
|
||||
|
||||
final Patient retrievedPatient = myPatientDao.read(pid1, new SystemRequestDetails());
|
||||
validateSavedPatientTags(retrievedPatient);
|
||||
|
||||
// Update the patient to create a ResourceHistoryTag record
|
||||
final List<Coding> tagsFromDbPatient = retrievedPatient.getMeta().getTag();
|
||||
assertEquals(1, tagsFromDbPatient.size());
|
||||
|
||||
tagsFromDbPatient.get(0)
|
||||
.setCode(expectedCode2)
|
||||
.setSystem(expectedSystem2)
|
||||
.setVersion(expectedVersion2)
|
||||
.setDisplay(expectedDisplay2)
|
||||
.setUserSelected(expectedUserSelected2);
|
||||
|
||||
myPatientDao.update(retrievedPatient, new SystemRequestDetails());
|
||||
final Patient retrievedUpdatedPatient = myPatientDao.read(pid1, new SystemRequestDetails());
|
||||
|
||||
final Meta meta = retrievedUpdatedPatient.getMeta();
|
||||
final List<Coding> tags = meta.getTag();
|
||||
tags.forEach(innerTag -> ourLog.info("TAGS: version: {}, userSelected: {}, code: {}, display: {}, system: {}",
|
||||
innerTag.getVersion(), innerTag.getUserSelected(), innerTag.getCode(), innerTag.getDisplay(), innerTag.getSystem()));
|
||||
final Coding tagFirstRep = meta.getTagFirstRep();
|
||||
ourLog.info("TAG FIRST REP: version: {}, userSelected: {}, code: {}, display: {}, system: {}",
|
||||
tagFirstRep.getVersion(), tagFirstRep.getUserSelected(), tagFirstRep.getCode(), tagFirstRep.getDisplay(), tagFirstRep.getSystem());
|
||||
|
||||
TagQtyExpectations expectedCounts = expectedTagCountMap.get(theTagStorageModeEnum);
|
||||
validateUpdatedPatientTags(expectedCounts, tags);
|
||||
|
||||
final List<ResourceHistoryTag> resourceHistoryTags2 = myResourceHistoryTagDao.findAll();
|
||||
|
||||
resourceHistoryTags2.forEach(historyTag -> {
|
||||
final TagDefinition tag = historyTag.getTag();
|
||||
ourLog.info("tagId: {}, resourceId: {}, version: {}, userSelected: {}, system: {}, code: {}, display: {}",
|
||||
historyTag.getTagId(), historyTag.getResourceId(), tag.getVersion(), tag.getUserSelected(), tag.getSystem(), tag.getCode(), tag.getDisplay());
|
||||
});
|
||||
|
||||
TagQtyExpectations expectedHistoryCounts = expectedHistoryTagCountMap.get(theTagStorageModeEnum);
|
||||
validateHistoryTags(expectedHistoryCounts, resourceHistoryTags2);
|
||||
}
|
||||
|
||||
|
||||
private void validateSavedPatientTags(Patient thePatient) {
|
||||
assertAll(
|
||||
() -> assertEquals(1, thePatient.getMeta().getTag().size()),
|
||||
() -> assertEquals(0, thePatient.getMeta().getSecurity().size()),
|
||||
() -> assertEquals(0, thePatient.getMeta().getProfile().size()),
|
||||
|
||||
() -> assertEquals(expectedSystem1, thePatient.getMeta().getTagFirstRep().getSystem()),
|
||||
() -> assertTrue(thePatient.getMeta().getTagFirstRep().getUserSelected()),
|
||||
() -> assertEquals(expectedCode1, thePatient.getMeta().getTagFirstRep().getCode()),
|
||||
() -> assertEquals(expectedVersion1, thePatient.getMeta().getTagFirstRep().getVersion()),
|
||||
() -> assertEquals(expectedUserSelected1, thePatient.getMeta().getTagFirstRep().getUserSelected())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private void validateUpdatedPatientTags(TagQtyExpectations theExpectedCounts, List<Coding> tags) {
|
||||
assertAll(
|
||||
() -> assertEquals(theExpectedCounts.theTagQty, tags.size()),
|
||||
() -> assertEquals(theExpectedCounts.theTagV1Qty, tags.stream()
|
||||
.filter(tag -> expectedSystem1.equals(tag.getSystem()))
|
||||
.filter(tag -> expectedCode1.equals(tag.getCode()))
|
||||
.filter(tag -> expectedDisplay1.equals(tag.getDisplay()))
|
||||
.filter(tag -> expectedVersion1.equals(tag.getVersion()))
|
||||
.filter(tag -> expectedUserSelected1 == tag.getUserSelected())
|
||||
.count()),
|
||||
() -> assertEquals(theExpectedCounts.theTagV2Qty, tags.stream()
|
||||
.filter(tag -> expectedSystem2.equals(tag.getSystem()))
|
||||
.filter(tag -> expectedCode2.equals(tag.getCode()))
|
||||
.filter(tag -> expectedDisplay2.equals(tag.getDisplay()))
|
||||
.filter(tag -> expectedVersion2.equals(tag.getVersion()))
|
||||
.filter(tag -> expectedUserSelected2 == tag.getUserSelected())
|
||||
.count())
|
||||
);
|
||||
}
|
||||
|
||||
private void validateHistoryTags(TagQtyExpectations theExpectedHistoryCounts, List<ResourceHistoryTag> theHistoryTags) {
|
||||
// validating this way because tags are a set so can be in any order
|
||||
assertAll(
|
||||
() -> assertEquals(theExpectedHistoryCounts.theTagQty, theHistoryTags.size()),
|
||||
() -> assertEquals(theExpectedHistoryCounts.theTagV1Qty, theHistoryTags.stream()
|
||||
.filter(resourceHistoryTag -> expectedSystem1.equals(resourceHistoryTag.getTag().getSystem()))
|
||||
.filter(resourceHistoryTag -> expectedCode1.equals(resourceHistoryTag.getTag().getCode()))
|
||||
.filter(resourceHistoryTag -> expectedDisplay1.equals(resourceHistoryTag.getTag().getDisplay()))
|
||||
.filter(resourceHistoryTag -> expectedVersion1.equals(resourceHistoryTag.getTag().getVersion()))
|
||||
.filter(resourceHistoryTag -> expectedUserSelected1 == resourceHistoryTag.getTag().getUserSelected())
|
||||
.count()),
|
||||
() -> assertEquals(theExpectedHistoryCounts.theTagV2Qty, theHistoryTags.stream()
|
||||
.filter(resourceHistoryTag -> expectedSystem2.equals(resourceHistoryTag.getTag().getSystem()))
|
||||
.filter(resourceHistoryTag -> expectedCode2.equals(resourceHistoryTag.getTag().getCode()))
|
||||
.filter(resourceHistoryTag -> expectedDisplay2.equals(resourceHistoryTag.getTag().getDisplay()))
|
||||
.filter(resourceHistoryTag -> expectedVersion2.equals(resourceHistoryTag.getTag().getVersion()))
|
||||
.filter(resourceHistoryTag -> expectedUserSelected2 == resourceHistoryTag.getTag().getUserSelected())
|
||||
.count())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Disabled // TODO JA: This test fails regularly, need to get a dedicated connection pool for tag creation
|
||||
@Test
|
||||
|
|
|
@ -47,13 +47,18 @@ class MemoryCacheServiceTest {
|
|||
String system = "http://example.com";
|
||||
TagTypeEnum type = TagTypeEnum.TAG;
|
||||
String code = "t";
|
||||
String version = "Ver 3.0";
|
||||
Boolean userSelected = true;
|
||||
|
||||
MemoryCacheService.TagDefinitionCacheKey cacheKey = new MemoryCacheService.TagDefinitionCacheKey(type, system, code);
|
||||
MemoryCacheService.TagDefinitionCacheKey cacheKey = new MemoryCacheService.TagDefinitionCacheKey(
|
||||
type, system, code, version, userSelected);
|
||||
|
||||
TagDefinition retVal = mySvc.getIfPresent(MemoryCacheService.CacheEnum.TAG_DEFINITION, cacheKey);
|
||||
assertThat(retVal, nullValue());
|
||||
|
||||
TagDefinition tagDef = new TagDefinition(type, system, code, "theLabel");
|
||||
tagDef.setVersion(version);
|
||||
tagDef.setUserSelected(userSelected);
|
||||
mySvc.put(MemoryCacheService.CacheEnum.TAG_DEFINITION, cacheKey, tagDef);
|
||||
|
||||
retVal = mySvc.getIfPresent(MemoryCacheService.CacheEnum.TAG_DEFINITION, cacheKey);
|
||||
|
|
|
@ -217,16 +217,22 @@ public class MemoryCacheService {
|
|||
private final TagTypeEnum myType;
|
||||
private final String mySystem;
|
||||
private final String myCode;
|
||||
private final String myVersion;
|
||||
private Boolean myUserSelected;
|
||||
private final int myHashCode;
|
||||
|
||||
public TagDefinitionCacheKey(TagTypeEnum theType, String theSystem, String theCode) {
|
||||
public TagDefinitionCacheKey(TagTypeEnum theType, String theSystem, String theCode, String theVersion, Boolean theUserSelected) {
|
||||
myType = theType;
|
||||
mySystem = theSystem;
|
||||
myCode = theCode;
|
||||
myVersion = theVersion;
|
||||
myUserSelected = theUserSelected;
|
||||
myHashCode = new HashCodeBuilder(17, 37)
|
||||
.append(myType)
|
||||
.append(mySystem)
|
||||
.append(myCode)
|
||||
.append(myVersion)
|
||||
.append(myUserSelected)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue