diff --git a/snomed/com.b2international.snowowl.snomed.core.rest.tests/src/com/b2international/snowowl/snomed/core/rest/components/SnomedComponentInactivationApiTest.java b/snomed/com.b2international.snowowl.snomed.core.rest.tests/src/com/b2international/snowowl/snomed/core/rest/components/SnomedComponentInactivationApiTest.java index 7ec3807a265..c99e8ca9be0 100644 --- a/snomed/com.b2international.snowowl.snomed.core.rest.tests/src/com/b2international/snowowl/snomed/core/rest/components/SnomedComponentInactivationApiTest.java +++ b/snomed/com.b2international.snowowl.snomed.core.rest.tests/src/com/b2international/snowowl/snomed/core/rest/components/SnomedComponentInactivationApiTest.java @@ -42,7 +42,28 @@ * @since 7.9.2 */ public class SnomedComponentInactivationApiTest extends AbstractSnomedApiTest { - + + @Test + public void descriptionInactivationIndicatorInactivation() { + String conceptId = createNewConcept(branchPath); + SnomedConcept concept = getConcept(conceptId, "descriptions()"); + String descriptionId = concept.getDescriptions().getItems().get(0).getId(); + + Map pendingMoveUpdate = ImmutableMap.of( + "inactivationProperties", new InactivationProperties(Concepts.PENDING_MOVE, null), + "commitComment", "Set to Pending Move"); + updateComponent(branchPath, SnomedComponentType.DESCRIPTION, descriptionId, pendingMoveUpdate).statusCode(204); + SnomedDescription description = getDescription(descriptionId, "members()"); + assertEquals(true, getIndicatorMember(description, Concepts.REFSET_DESCRIPTION_INACTIVITY_INDICATOR).isActive()); + + Map indicatorStatusUpdate = ImmutableMap.of( + "inactivationProperties", new InactivationProperties(Concepts.PENDING_MOVE, null, false), + "commitComment", "Inactivate Inactivation Indicator"); + updateComponent(branchPath, SnomedComponentType.DESCRIPTION, descriptionId, indicatorStatusUpdate).statusCode(204); + SnomedDescription updatedDescription = getDescription(descriptionId, "members()"); + assertEquals(false, getIndicatorMember(updatedDescription, Concepts.REFSET_DESCRIPTION_INACTIVITY_INDICATOR).isActive()); + } + @Test public void reuseConceptAndDescriptionInactivationIndicators() throws Exception { // create a concept diff --git a/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/core/domain/InactivationProperties.java b/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/core/domain/InactivationProperties.java index aaace9ae571..6c6b384745a 100644 --- a/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/core/domain/InactivationProperties.java +++ b/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/core/domain/InactivationProperties.java @@ -25,6 +25,7 @@ public final class InactivationProperties implements Serializable { private static final long serialVersionUID = 1L; + private Boolean inactivationIndicatorStatus; private SnomedConcept inactivationIndicator; private List associationTargets; @@ -36,6 +37,12 @@ public InactivationProperties(String inactivationIndicatorId, List associationTargets, Boolean inactivationIndicatorStatus) { + setInactivationIndicatorId(inactivationIndicatorId); + setAssociationTargets(associationTargets); + setInactivationIndicatorStatus(inactivationIndicatorStatus); + } + /** * Returns the component's corresponding active inactivation indicator member value. In case of multiple values present in the corresponding * inactivation indicator reference set this value will return the first active occurrence from that refset. @@ -70,5 +77,13 @@ public List getAssociationTargets() { public void setAssociationTargets(List associationTargets) { this.associationTargets = associationTargets; } + + public Boolean getInactivationIndicatorStatus() { + return inactivationIndicatorStatus; + } + + public void setInactivationIndicatorStatus(Boolean inactivationIndicatorStatus) { + this.inactivationIndicatorStatus = inactivationIndicatorStatus; + } } diff --git a/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/BaseComponentMemberUpdateRequest.java b/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/BaseComponentMemberUpdateRequest.java index dc6e895df46..e2927d2c4f6 100644 --- a/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/BaseComponentMemberUpdateRequest.java +++ b/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/BaseComponentMemberUpdateRequest.java @@ -68,6 +68,28 @@ protected final boolean ensureMemberActive(final TransactionContext context, fin } } + + protected final boolean ensureStatusChanged(final TransactionContext context, final SnomedReferenceSetMember existingMember, + final Boolean newMemberStatus, final SnomedRefSetMemberIndexEntry.Builder updatedMember) { + if (newMemberStatus == null) { + return false; + } else if (!existingMember.isActive() && newMemberStatus) { + if (LOG.isDebugEnabled()) { LOG.debug("Reactivating {} member {}.", getMemberType(), existingMember.getId()); } + updatedMember.active(true); + updateModule(context, existingMember, updatedMember, context.service(ModuleIdProvider.class).apply(componentToUpdate)); + unsetEffectiveTime(existingMember, updatedMember); + return true; + } else if (existingMember.isActive() && !newMemberStatus) { + if (LOG.isDebugEnabled()) { LOG.debug("Inactivating {} member {}.", getMemberType(), existingMember.getId()); } + updatedMember.active(false); + updateModule(context, existingMember, updatedMember, context.service(ModuleIdProvider.class).apply(componentToUpdate)); + unsetEffectiveTime(existingMember, updatedMember); + return true; + } else { + if (LOG.isDebugEnabled()) { LOG.debug("{} member {} already {}, not updating.", getMemberType(), existingMember.getId(), newMemberStatus ? "active" : "inactive"); } + return false; + } + } protected final boolean removeOrDeactivate(final TransactionContext context, final SnomedReferenceSetMember existingMember, final SnomedRefSetMemberIndexEntry.Builder updatedMember) { if (!existingMember.isReleased()) { diff --git a/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/SnomedComponentUpdateRequest.java b/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/SnomedComponentUpdateRequest.java index 5fbd53071fb..166a42998b7 100644 --- a/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/SnomedComponentUpdateRequest.java +++ b/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/SnomedComponentUpdateRequest.java @@ -100,6 +100,7 @@ protected final , T extends Snom final boolean currentStatus = component.isActive(); final boolean newStatus = isActive() == null ? currentStatus : isActive(); final String newInactivationIndicatorId = getInactivationProperties() == null || getInactivationProperties().getInactivationIndicatorId() == null ? "" : getInactivationProperties().getInactivationIndicatorId(); + final Boolean newInactivationIndicatorStatus = getInactivationProperties() == null ? null : getInactivationProperties().getInactivationIndicatorStatus(); final ImmutableMultimap.Builder newAssociationTargets = ImmutableMultimap.builder(); if (getInactivationProperties() != null && !CompareUtils.isEmpty(getInactivationProperties().getAssociationTargets())) { @@ -114,7 +115,7 @@ protected final , T extends Snom // (using default values if not given) inactivateComponent(context, component, updatedComponent); - updateInactivationIndicator(context, component, newInactivationIndicatorId); + updateInactivationIndicator(context, component, newInactivationIndicatorId, newInactivationIndicatorStatus); updateAssociationTargets(context, component, newAssociationTargets.build()); postInactivateComponent(context, component, updatedComponent); return true; @@ -124,7 +125,7 @@ protected final , T extends Snom // Inactive --> Active: concept reactivation, clear indicator and association targets reactivateComponent(context, component, updatedComponent); - updateInactivationIndicator(context, component, newInactivationIndicatorId); + updateInactivationIndicator(context, component, newInactivationIndicatorId, newInactivationIndicatorStatus); updateAssociationTargets(context, component, newAssociationTargets.build()); postReactivateComponent(context, component, updatedComponent); return true; @@ -134,7 +135,10 @@ protected final , T extends Snom // Same status, allow indicator and/or association targets to be updated if required // (using original values that can be null) - updateInactivationIndicator(context, component, getInactivationProperties() != null ? getInactivationProperties().getInactivationIndicatorId() : null); + updateInactivationIndicator(context, + component, + getInactivationProperties() != null ? getInactivationProperties().getInactivationIndicatorId() : null, + newInactivationIndicatorStatus); updateAssociationTargets(context, component, newAssociationTargets.build()); return false; @@ -173,14 +177,15 @@ protected final void updateAssociationTargets(final TransactionContext context, } new SnomedAssociationTargetUpdateRequest(concept, associationTargets).execute(context); } - - protected final void updateInactivationIndicator(final TransactionContext context, final SnomedComponentDocument concept, final String newInactivationIndicatorId) { + + protected final void updateInactivationIndicator(final TransactionContext context, final SnomedComponentDocument concept, final String newInactivationIndicatorId, Boolean newInactivationIndicatorStatus) { if (newInactivationIndicatorId == null) { return; } final SnomedInactivationReasonUpdateRequest inactivationUpdateRequest = new SnomedInactivationReasonUpdateRequest(concept, getInactivationIndicatorRefSetId()); inactivationUpdateRequest.setInactivationValueId(newInactivationIndicatorId); + inactivationUpdateRequest.setInactivationMemberStatus(newInactivationIndicatorStatus); inactivationUpdateRequest.execute(context); } diff --git a/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/SnomedInactivationReasonUpdateRequest.java b/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/SnomedInactivationReasonUpdateRequest.java index 1d1751305cb..9b0785df61a 100644 --- a/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/SnomedInactivationReasonUpdateRequest.java +++ b/snomed/com.b2international.snowowl.snomed.datastore/src/com/b2international/snowowl/snomed/datastore/request/SnomedInactivationReasonUpdateRequest.java @@ -77,6 +77,7 @@ final class SnomedInactivationReasonUpdateRequest extends BaseComponentMemberUpd private final String inactivationRefSetId; private String inactivationValueId; + private Boolean inactivationMemberStatus; SnomedInactivationReasonUpdateRequest(final SnomedComponentDocument componentToUpdate, final String inactivationRefSetId) { @@ -87,7 +88,11 @@ final class SnomedInactivationReasonUpdateRequest extends BaseComponentMemberUpd void setInactivationValueId(final String inactivationValueId) { this.inactivationValueId = inactivationValueId; } - + + public void setInactivationMemberStatus(Boolean inactivationMemberStatus) { + this.inactivationMemberStatus = inactivationMemberStatus; + } + @Override protected boolean canUpdate(TransactionContext context) { // Null leaves inactivation reason unchanged, empty string clears existing inactivation reason @@ -130,7 +135,7 @@ protected void doExecute(TransactionContext context, SnomedComponentDocument com if (Objects.equals(existingValueId, inactivationValueId)) { // Exact match, just make sure that the member is active - changed = ensureMemberActive(context, existingMember, updatedMember); + changed = ensureStatusChanged(context, existingMember, inactivationMemberStatus, updatedMember); } else if (!CLEAR.equals(inactivationValueId)) { // Re-use this member, if the intention was not to remove the existing value @@ -172,5 +177,5 @@ protected void doExecute(TransactionContext context, SnomedComponentDocument com .addTo(context); } } - + }