use of com.b2international.snowowl.snomed.core.domain.SnomedConcept in project snow-owl by b2ihealthcare.
the class SnomedExtensionUpgradeTest method upgrade10DonatedConceptAndDescriptionsAndRelationships.
@Test
public void upgrade10DonatedConceptAndDescriptionsAndRelationships() {
// create extension on the latest SI VERSION
CodeSystem extension = createExtension(latestInternationalVersion, branchPath.lastSegment());
String extensionModuleId = createModule(extension);
String extensionFsnTerm = "FSN of concept";
String extensionPtTerm = "PT of concept";
String extensionSynonymTerm = "Synonym of extension concept";
Json fsnRequestBody = Json.object("typeId", Concepts.FULLY_SPECIFIED_NAME, "term", extensionFsnTerm, "languageCode", DEFAULT_LANGUAGE_CODE, "acceptability", SnomedApiTestConstants.UK_PREFERRED_MAP);
Json ptRequestBody = Json.object("typeId", Concepts.SYNONYM, "term", extensionPtTerm, "languageCode", DEFAULT_LANGUAGE_CODE, "acceptability", SnomedApiTestConstants.UK_PREFERRED_MAP);
Json synonymRequestBody = Json.object("typeId", Concepts.SYNONYM, "term", extensionSynonymTerm, "languageCode", DEFAULT_LANGUAGE_CODE, "acceptability", SnomedApiTestConstants.UK_ACCEPTABLE_MAP);
Json statedIsa = Json.object("typeId", Concepts.IS_A, "destinationId", Concepts.ROOT_CONCEPT, "characteristicTypeId", Concepts.STATED_RELATIONSHIP);
Json inferredIsa = Json.object("typeId", Concepts.IS_A, "destinationId", Concepts.ROOT_CONCEPT, "characteristicTypeId", Concepts.INFERRED_RELATIONSHIP);
Json extensionConceptRequestBody = Json.object("namespaceId", Concepts.B2I_NAMESPACE, "moduleId", extensionModuleId, "descriptions", Json.array(fsnRequestBody, ptRequestBody, synonymRequestBody), "relationships", Json.array(statedIsa, inferredIsa));
String extensionConceptId = createConcept(extension.getResourceURI(), extensionConceptRequestBody);
// create new extension version
createVersion(extension.getId(), "v1", LocalDate.now()).statusCode(201);
SnomedConcept extensionConcept = getConcept(extension.getResourceURI(), extensionConceptId, "descriptions()", "relationships()");
String extensionFsnId = getFirstMatchingDescription(extensionConcept, extensionFsnTerm).getId();
String extensionPtId = getFirstMatchingDescription(extensionConcept, extensionPtTerm).getId();
String extensionSynonymId = getFirstMatchingDescription(extensionConcept, extensionSynonymTerm).getId();
String extensionStatedIsaId = getFirstRelationshipId(extensionConcept, Concepts.STATED_RELATIONSHIP);
String extensionInferredIsaId = getFirstRelationshipId(extensionConcept, Concepts.INFERRED_RELATIONSHIP);
// simulate donation via concept create and versioning
// create INT concept with same ID and with same description and relationship IDs
String intConceptId = createConcept(SnomedContentRule.SNOMEDCT, Json.object("id", extensionConceptId, "moduleId", Concepts.MODULE_SCT_CORE, "descriptions", Json.array(fsnRequestBody.with("id", extensionFsnId), ptRequestBody.with("id", extensionPtId)), "relationships", Json.array(statedIsa.with("id", extensionStatedIsaId), inferredIsa.with("id", extensionInferredIsaId))));
LocalDate effectiveTime = getNextAvailableEffectiveDate(SNOMEDCT);
createVersion(SNOMEDCT, effectiveTime).statusCode(201);
// start upgrade to the new available upgrade version
CodeSystem upgradeCodeSystem = createExtensionUpgrade(extension.getResourceURI(), CodeSystem.uri(SNOMEDCT, effectiveTime.toString()));
SnomedConcept donatedConceptInExtension = getConcept(upgradeCodeSystem.getResourceURI(), intConceptId, "descriptions()", "relationships()");
// validate components of donated concept on extension branch
// same ID, different module
assertEquals(donatedConceptInExtension.getId(), extensionConcept.getId());
assertNotEquals(donatedConceptInExtension.getModuleId(), extensionConcept.getModuleId());
SnomedDescription donatedFsn = getFirstMatchingDescription(donatedConceptInExtension, extensionFsnTerm);
assertEquals(extensionFsnId, donatedFsn.getId());
assertEquals(Concepts.MODULE_SCT_CORE, donatedFsn.getModuleId());
SnomedDescription donatedPt = getFirstMatchingDescription(donatedConceptInExtension, extensionPtTerm);
assertEquals(extensionPtId, donatedPt.getId());
assertEquals(Concepts.MODULE_SCT_CORE, donatedPt.getModuleId());
Set<String> descriptionIds = donatedConceptInExtension.getDescriptions().getItems().stream().map(SnomedDescription::getId).collect(Collectors.toSet());
assertThat(descriptionIds).hasSize(3).contains(extensionSynonymId);
Set<String> relationshipIds = donatedConceptInExtension.getRelationships().getItems().stream().map(SnomedRelationship::getId).collect(Collectors.toSet());
assertThat(relationshipIds).hasSize(2).contains(extensionStatedIsaId, extensionInferredIsaId);
}
use of com.b2international.snowowl.snomed.core.domain.SnomedConcept in project snow-owl by b2ihealthcare.
the class SnomedImportApiTest method import29ImportExistingConceptAsUnpublished.
@Test
public void import29ImportExistingConceptAsUnpublished() throws Exception {
getComponent(branchPath, SnomedComponentType.CONCEPT, "100005").statusCode(404);
importArchive("SnomedCT_Release_INT_20210502_concept_w_eff_time.zip");
SnomedConcept conceptBefore = getComponent(branchPath, SnomedComponentType.CONCEPT, "100005").statusCode(200).extract().as(SnomedConcept.class);
importArchive("SnomedCT_Release_INT_20210502_concept_wo_eff_time.zip");
SnomedConcept conceptAfter = getComponent(branchPath, SnomedComponentType.CONCEPT, "100005").statusCode(200).extract().as(SnomedConcept.class);
assertEquals(EffectiveTimes.parse("2021-05-02"), conceptBefore.getEffectiveTime());
assertTrue(conceptBefore.isReleased());
assertEquals(EffectiveTimes.toDate(EffectiveTimes.UNSET_EFFECTIVE_TIME), conceptAfter.getEffectiveTime());
assertTrue(conceptAfter.isReleased());
}
use of com.b2international.snowowl.snomed.core.domain.SnomedConcept in project snow-owl by b2ihealthcare.
the class SnomedVersioningApiTest method forceCreateVersionShouldUpdateEffectiveTime.
@Test
public void forceCreateVersionShouldUpdateEffectiveTime() {
final String versionName = "forceCreateVersionShouldUpdateEffectiveTime";
ResourceURI codeSystemVersionURI = SnomedContentRule.SNOMEDCT.withPath(versionName);
LocalDate versionEffectiveDate = getNextAvailableEffectiveDate(INT_CODESYSTEM);
createVersion(INT_CODESYSTEM, versionName, versionEffectiveDate).statusCode(201);
String conceptId = createConcept(SnomedContentRule.SNOMEDCT, SnomedRestFixtures.childUnderRootWithDefaults());
SnomedConcept afterFailedVersioning = getConcept(SnomedContentRule.SNOMEDCT, conceptId);
assertEquals(null, afterFailedVersioning.getEffectiveTime());
// Should succeed to recreate version with the force flag set
createVersion(INT_CODESYSTEM, versionName, versionEffectiveDate, true).statusCode(201);
SnomedConcept afterForceVersioning = getConcept(codeSystemVersionURI, conceptId);
assertEquals(versionEffectiveDate, afterForceVersioning.getEffectiveTime());
}
use of com.b2international.snowowl.snomed.core.domain.SnomedConcept in project snow-owl by b2ihealthcare.
the class SnomedEclLabelerRequest method execute.
@Override
public LabeledEclExpressions execute(BranchContext context) {
final EclSerializer eclSerializer = context.service(EclSerializer.class);
final EclParser eclParser = context.service(EclParser.class);
final Set<String> conceptIdsToLabel = Sets.newHashSetWithExpectedSize(expressions.size());
final Map<String, ExpressionConstraint> queries = Maps.newHashMapWithExpectedSize(expressions.size());
final LinkedHashMap<String, Object> errors = Maps.newLinkedHashMap();
for (String expression : expressions) {
if (Strings.isNullOrEmpty(expression)) {
continue;
}
try {
ExpressionConstraint query = queries.computeIfAbsent(expression, (key) -> eclParser.parse(key));
conceptIdsToLabel.addAll(collect(query));
} catch (ApiException e) {
if (e instanceof SyntaxException) {
errors.put(expression, List.copyOf(((SyntaxException) e).getAdditionalInfo().values()));
} else if (e instanceof BadRequestException) {
errors.put(expression, e.getMessage());
} else {
throw e;
}
}
}
if (!errors.isEmpty()) {
BadRequestException badRequestException = new BadRequestException("One or more ECL syntax errors");
badRequestException.withAdditionalInfo("erroneousExpressions", errors);
throw badRequestException;
}
// fetch all concept labels
final Map<String, String> labels = SnomedRequests.prepareSearchConcept().filterByIds(conceptIdsToLabel).setLimit(conceptIdsToLabel.size()).setExpand(descriptionType.toLowerCase() + "()").setLocales(locales()).build().execute(context).stream().collect(Collectors.toMap(SnomedConcept::getId, this::extractLabel));
// expand all queries with labels
List<String> results = expressions.stream().map(expression -> {
if (Strings.isNullOrEmpty(expression)) {
return expression;
} else {
ExpressionConstraint query = queries.get(expression);
expand(query, labels);
return eclSerializer.serialize(query);
}
}).collect(Collectors.toList());
return new LabeledEclExpressions(results);
}
use of com.b2international.snowowl.snomed.core.domain.SnomedConcept in project snow-owl by b2ihealthcare.
the class SnomedQueryOptimizer method optimize.
@Override
public QueryExpressionDiffs optimize(BranchContext context, Options params) {
final Collection<QueryExpression> inclusions = params.getCollection(QueryOptimizer.OptionKey.INCLUSIONS, QueryExpression.class);
final List<ExtendedLocale> locales = params.getList(QueryOptimizer.OptionKey.LOCALES, ExtendedLocale.class);
final EclParser eclParser = context.service(EclParser.class);
final LoadingCache<String, ExpressionConstraint> eclCache = CacheBuilder.newBuilder().build(CacheLoader.from(eclParser::parse));
final Multimap<String, QueryExpression> singleConceptInclusions = FluentIterable.from(inclusions).filter(ex -> isSingleConceptExpression(eclCache, ex.getQuery())).index(ex -> toSingleConceptId(eclCache, ex.getQuery()));
// if there are no single concept inclusions to optimize, exit early
if (singleConceptInclusions.isEmpty()) {
return new QueryExpressionDiffs(Collections.emptyList());
}
// Record the ancestors (both direct and indirect) of each single concept inclusion
final Multimap<String, QueryExpression> membersByAncestor = HashMultimap.create();
SnomedRequests.prepareSearchConcept().filterByIds(singleConceptInclusions.keySet()).setLimit(singleConceptInclusions.keySet().size()).stream(context).flatMap(SnomedConcepts::stream).forEach(child -> {
final Collection<QueryExpression> childExpressions = singleConceptInclusions.get(child.getId());
final List<String> parentIds = child.getParentIdsAsString();
final List<String> ancestorIds = child.getAncestorIdsAsString();
parentIds.forEach(parentId -> {
if (!IComponent.ROOT_ID.equals(parentId) && !Concepts.ROOT_CONCEPT.equals(parentId)) {
membersByAncestor.putAll(parentId, childExpressions);
}
});
ancestorIds.forEach(ancestorId -> {
if (!IComponent.ROOT_ID.equals(ancestorId) && !Concepts.ROOT_CONCEPT.equals(ancestorId)) {
membersByAncestor.putAll(ancestorId, childExpressions);
}
});
});
// Get number of referenced descendants (taking possible duplicates into account)
final Map<String, Long> uniqueDescendantsByParent = ImmutableMap.copyOf(Maps.transformValues(membersByAncestor.asMap(), descendants -> descendants.stream().map(QueryExpression::getQuery).distinct().count()));
final ImmutableList.Builder<QueryExpressionDiff> diffs = ImmutableList.builder();
// references can be replaced with a single << expression.
for (Entry<String, Long> uniqueDescendantsByParentEntry : uniqueDescendantsByParent.entrySet()) {
SnomedConcept parent = SnomedRequests.prepareGetConcept(uniqueDescendantsByParentEntry.getKey()).setLocales(locales).setExpand("pt(),descendants(direct:false,limit:0)").build().execute(context);
final String parentId = parent.getId();
final int referencedDescendants = Ints.checkedCast(uniqueDescendantsByParent.get(parentId));
final int totalDescendants = parent.getDescendants().getTotal();
if (totalDescendants == referencedDescendants) {
final List<QueryExpression> remove = List.copyOf(membersByAncestor.get(parentId).stream().filter(ex -> !ex.isPinned()).collect(Collectors.toList()));
// The optimization is a "net win" if we can remove at least two clauses from the original
if (remove.size() > 1) {
final QueryExpression replacement = new QueryExpression(IDs.base64UUID(), String.format("<%s%s", parent.getId(), getTerm(parent)), false);
final List<QueryExpression> addToInclusion = List.of(replacement);
final List<QueryExpression> addToExclusion = List.of();
final QueryExpressionDiff diff = new QueryExpressionDiff(addToInclusion, addToExclusion, remove);
diffs.add(diff);
}
}
}
return new QueryExpressionDiffs(diffs.build());
}
Aggregations