From ab6754fd800c4ef4180ca1b2cbaec6fd40c5eca6 Mon Sep 17 00:00:00 2001 From: Darryn McGaw Date: Fri, 25 Oct 2024 16:47:10 +0100 Subject: [PATCH] MAINT-2309 Prevent copyConcepts from working against versioned branches MAINT-2309 Remove public modifier --- .../core/data/services/ConceptService.java | 11 ++++ .../data/services/ConceptServiceTest.java | 62 +++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/src/main/java/org/snomed/snowstorm/core/data/services/ConceptService.java b/src/main/java/org/snomed/snowstorm/core/data/services/ConceptService.java index e1920ed10..3deb999bd 100644 --- a/src/main/java/org/snomed/snowstorm/core/data/services/ConceptService.java +++ b/src/main/java/org/snomed/snowstorm/core/data/services/ConceptService.java @@ -870,6 +870,17 @@ public List copyConcepts(String ecl, String sourceBranchPath, Strin final Branch sourceBranch = branchService.findBranchOrThrow(sourceBranchPath, true); final Branch destinationBranch = branchService.findBranchOrThrow(destinationBranchPath, true); + CodeSystem codeSystem = codeSystemService.findClosestCodeSystemUsingAnyBranch(destinationBranchPath, false); + if (codeSystem != null) { + List codeSystemVersions = codeSystemService.findAllVersions(codeSystem.getShortName(), true, true); + String branchPath = destinationBranch.getPath(); + for (CodeSystemVersion codeSystemVersion : codeSystemVersions) { + if (Objects.equals(branchPath, codeSystemVersion.getBranchPath())) { + throw new ServiceException("Cannot donate concepts from " + sourceBranchPath + " to versioned " + destinationBranchPath); + } + } + } + if (getDefaultModuleId(sourceBranch).equals(getDefaultModuleId(destinationBranch))) { throw new ServiceException("Cannot donate concepts from " + sourceBranchPath + " to " + destinationBranchPath + " as they are from the same module: " + getDefaultModuleId(sourceBranch)); } diff --git a/src/test/java/org/snomed/snowstorm/core/data/services/ConceptServiceTest.java b/src/test/java/org/snomed/snowstorm/core/data/services/ConceptServiceTest.java index 60466e974..65252d7b7 100644 --- a/src/test/java/org/snomed/snowstorm/core/data/services/ConceptServiceTest.java +++ b/src/test/java/org/snomed/snowstorm/core/data/services/ConceptServiceTest.java @@ -17,6 +17,8 @@ import org.snomed.snowstorm.AbstractTest; import org.snomed.snowstorm.config.Config; import org.snomed.snowstorm.core.data.domain.*; +import org.snomed.snowstorm.core.data.domain.review.MergeReview; +import org.snomed.snowstorm.core.data.domain.review.MergeReviewConceptVersions; import org.snomed.snowstorm.core.data.services.pojo.AsyncConceptChangeBatch; import org.snomed.snowstorm.core.data.services.pojo.DescriptionCriteria; import org.snomed.snowstorm.core.data.services.pojo.MemberSearchRequest; @@ -3011,6 +3013,66 @@ void testActivatingInvalidAxiomThrowsException() throws ServiceException { }); } + @Test + void copyConcepts_ShouldThrowException_WhenTargetIsVersionedBranch() throws ServiceException { + String intMain = "MAIN"; + String extMain = "MAIN/SNOMEDCT-XX"; + Map intPreferred = Map.of(US_EN_LANG_REFSET, descriptionAcceptabilityNames.get(PREFERRED), GB_EN_LANG_REFSET, descriptionAcceptabilityNames.get(PREFERRED)); + Map intAcceptable = Map.of(US_EN_LANG_REFSET, descriptionAcceptabilityNames.get(PREFERRED), GB_EN_LANG_REFSET, descriptionAcceptabilityNames.get(ACCEPTABLE)); + String ci = "CASE_INSENSITIVE"; + Concept concept; + Description description; + CodeSystem codeSystem; + + // Create International Concept + concept = new Concept() + .addDescription(new Description("Medicine (medicine)").setTypeId(FSN).setCaseSignificance(ci).setAcceptabilityMap(intPreferred)) + .addDescription(new Description("Medicine").setTypeId(SYNONYM).setCaseSignificance(ci).setAcceptabilityMap(intPreferred)) + .addAxiom(new Relationship(ISA, SNOMEDCT_ROOT)) + .addRelationship(new Relationship(ISA, SNOMEDCT_ROOT)); + concept = conceptService.create(concept, intMain); + String medicineId = concept.getConceptId(); + + // Version International + codeSystem = codeSystemService.find("SNOMEDCT"); + codeSystemService.createVersion(codeSystem, 20240101, "20240101"); + + // Create Extension + codeSystem = codeSystemService.createCodeSystem(new CodeSystem("SNOMEDCT-XX", extMain)); + concept = conceptService.create( + new Concept() + .addDescription(new Description("Extension module (module)").setTypeId(FSN).setCaseSignificance(ci).setAcceptabilityMap(intPreferred)) + .addDescription(new Description("Extension module").setTypeId(SYNONYM).setCaseSignificance(ci).setAcceptabilityMap(intPreferred)) + .addAxiom(new Relationship(ISA, MODULE)), + extMain + ); + String extModuleA = concept.getConceptId(); + branchService.updateMetadata(extMain, Map.of(Config.DEFAULT_MODULE_ID_KEY, extModuleA, Config.EXPECTED_EXTENSION_MODULES, List.of(extModuleA))); + + // Create Extension concept + concept = new Concept() + .setModuleId(extModuleA) + .addDescription(new Description("Paracetamol (medicine)").setTypeId(FSN).setCaseSignificance(ci).setAcceptabilityMap(intPreferred)) + .addDescription(new Description("Paracetamol").setTypeId(SYNONYM).setCaseSignificance(ci).setAcceptabilityMap(intPreferred)) + .addAxiom(new Relationship(ISA, medicineId)) + .addRelationship(new Relationship(ISA, medicineId)); + concept = conceptService.create(concept, extMain); + String paracetamolId = concept.getConceptId(); + + // Version Extension + codeSystem = codeSystemService.find("SNOMEDCT-XX"); + codeSystemService.createVersion(codeSystem, 20240102, "20240102"); + + // Copy Extension to International + assertThrows(ServiceException.class, () -> { + conceptService.copyConcepts("<< " + paracetamolId, extMain, "MAIN/2024-01-01", true); + }); + + // Assert copying failed + concept = conceptService.find(paracetamolId, "MAIN/2024-01-01"); + assertNull(concept); + } + private Description getDescriptionByTerm(Concept concept, String term) { if (concept == null) { return null;